为什么我要再把这道题目拿出来,我是真的想提醒一下自己。
做算法的题目和数学题目其实是一样的,没有完整的思路,没有切实的方法,
没有及其的小心,细心你是做不出来题目的。
你必须要当心,敲代码的时候时刻看着上面自己敲得是否合适,不合适或者自己现在不知道
合适不合适,或者有一定的几率错的地方一定要标注下来。
下面的代码,自己这几天刚刚实现过,但是现在写起来还是写错了好多次。原因就是自己没有注意int*int是极有可能
出现long long的,而自己却没有注意。
#include <stdio.h> #include <string.h> #include <iostream> #include <string> using namespace std; int N, M, P; int quick_pow(int a, int n) { int ans = 1; while (n) { if (n & 1) { ans = (long long int)ans * a % P;//这里的long long int也是必须的 } a = (long long int)a * a % P; // 也是必须的. n >>= 1; } return ans; } int C(int n, int m) { if (n < m) { return 0; } int ans = 1; for (int i = 1; i <= m; i++) { int t = (n - m + i) % P; int b = i % P; int temp = (long long int)t * quick_pow(b, P - 2) % P; //这里的long long int也是必须的; ans = (long long int)ans * temp % P;//这里的long long int 也是必须的 } return ans; } int lucas(int n, int m) { if (m == 0) { return 1; } return (long long int)C(n % P, m % P) * lucas(n / P, m / P) % P; //所有的这些(long long int)都是要加上的,你不能肯定所有的数据都在int } int main() { while (scanf("%d%d%d", &N, &M, &P) != EOF) { int t = N - M + 1; if (t < M) { printf("0\n"); continue; } if (t - M < M) { M = t - M; } int ans = lucas(t, M); printf("%d\n", ans); } // system("pause"); return 0; }
再贴出来一个用extgcd求逆元的代码,代码运行要快的多了,180ms而上面的590
以后还是要尽量用extgcd,,注意求出来之后要 x要处理一下,因为有可能出现的数是负数,所以
x = (x % p + p)%p
贴出代码:
#include <stdio.h> #include <string.h> #include <iostream> #include <string> using namespace std; /* *一般一出现素数作为MOD的题目,基本上就是lucas了; *而这类题目的难点也就在推导出排列组合公式,后面的lucas,快速幂什么的 *都是浮云!还是要做个排列组合的专题的。 *时间才用了180ms,比quick_pow要快很多,以后尽量还是要用extgcd来求逆元 */ int N, M, P; /* int quick_pow(int a, int n) { int ans = 1; while (n) { if (n & 1) { ans = (long long int)ans * a % P;//这里的long long int也是必须的 } a = (long long int)a * a % P; // 也是必须的. n >>= 1; } return ans; } */ int extgcd(int a, int b, int &x, int &y) { if (b == 0) { x = 1; y = 0; return a; } int d = extgcd(b, a % b, x, y); int t = x; x = y; y = t - a / b * y; return d; } int C(int n, int m) { if (n < m) { return 0; } int ans = 1; for (int i = 1; i <= m; i++) { int t = (n - m + i) % P; int b = i % P; // int temp = (long long int)t * quick_pow(b, P - 2) % P; //这里的long long int也是必须的; int x, y; int d = extgcd(b, P, x, y); x = (x % P + P) % P;//为什么不可以呀???晕死了就!!! int temp = (long long int)t * x % P; //这里也要mod P, ans = (long long int)ans * temp % P;//这里的long long int 也是必须的 } return ans; } int lucas(int n, int m) { if (m == 0) { return 1; } return (long long int)C(n % P, m % P) * lucas(n / P, m / P) % P; //所有的这些(long long int)都是要加上的,你不能肯定所有的数据都在int } int main() { while (scanf("%d%d%d", &N, &M, &P) != EOF) { int t = N - M + 1; if (t < M) { printf("0\n"); continue; } if (t - M < M) { M = t - M; } int ans = lucas(t, M); printf("%d\n", ans); } // system("pause"); return 0; }