题干:
2018百度之星复赛晋级名单出炉(增加20%晋级名额)~ |
zhx's contestTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 3779 Accepted Submission(s): 1226 Problem Description As one of the most powerful brushes, zhx is required to give his juniors n problems.
Input Multiply test cases(less than 1000 ). Seek EOF as the end of the file.
Output For each test case, output a single line indicating the answer.
Sample Input
2 233 3 5
Sample Output
2 1 Hint In the first case, both sequence {1, 2} and {2, 1} are legal. In the second case, sequence {1, 2, 3}, {1, 3, 2}, {2, 1, 3}, {2, 3, 1}, {3, 1, 2}, {3, 2, 1} are legal, so the answer is 6 mod 5 = 1
Source BestCoder Round #33
|
解题报告:
首先这题找规律,题目推出来通式是:2^n - 2。证明如下:
推的过程就是一共有四种情况: 升升,升降,降升,降降,其中升升和降降最简单,一共有两种,复杂的就是升降和降升这两种情况,首先来看降生,那么ai一定是最小值,因为两边都算ai了,所有当在第一个空的时候,前面一共有Cn-11, 后面就自动的确定了,在第二位的时候,有Cn-12, 同理到最后Cn-1n-2,所以加起来就是2n-1-2,这是降升,同理升降也是这么多,所以最后结果就是(2n-1-2) * 2 + 2 = 2n-2;
注意的是这题的乘法不能直接乘法,因为longlong * longlong可能会爆掉,所以这里用快速乘法,把longlong * longlong转化成longlong + longlong 去做。
AC代码:
#include<iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef long long LL;LL qmul(LL a, LL k, LL mod) { //快速乘法LL ans = 0;//加法的幺元while (k) {if (k & 1) ans = (ans + a)%mod;a = (a + a) % mod;//和快速幂一样,只不过这里是加k >>= 1;}return ans;
}
LL qpow(LL a, LL k, LL mod) { //快速幂LL ans = 1;while (k) {if (k & 1) ans = qmul(ans, a, mod);//不能直接乘a = qmul(a, a, mod);k >>= 1;}return ans;
}int main() {LL n, p;while (~scanf("%I64d %I64d", &n, &p)) {if (n == 1) { //特判一下printf("%I64d\n", 1 % p);continue;}printf("%I64d\n", (qpow(2, n, p) - 2 + p) % p);//这一步注意,不要为负数}return 0;
}