组合数取余
P不是素数,P是素数
1)P是素数
- Lucas theorem
- m = mk * p^k + mk-1 * p^k-1 +... +m1 * p + m0;
- n = nk * p^k + nk-1 * p^k-1 +... + n1 * p + n0;
- C(m,n)=C(mk,nk)*C(mk-1,nk-1)*...*C(m1,n1)*C(m0,n0);
- 【题目大意】
- 求C(n+m,n) % p的值。
- 保证p是素数。
C(m,n)%p=m!/(n!*(m-n)!)%p
此时使用逆元,或扩展欧几里德
2)P是任意数时
hdu 3037
方法一: #include<stdio.h> #define LL long long #define nnum 100001 int num[nnum], x, y; void init(int p) { int i; LL te; num[0] = 1; for (i = 1; i <= p; i++) { te = (LL) i; te = te * num[i - 1] % p; num[i] = (int) te; } } int modular_exp(int a, int b, int c) { LL res, te; res = 1, te = a % c; while (b) { if (b & 1) { res = res * te % c; } te = te * te % c; b >>= 1; } return (int) res; } int gcd(int a, int b) { if (a < b) { a ^= b, b ^= a, a ^= b; } if (b == 0) { return a; } return gcd(b, a % b); } void extend_gcd(int a, int b) { if (b == 0) { x = 1, y = 0; return; } extend_gcd(b, a % b); int tx = x; x = y, y = tx - a / b * y; } int C(int a, int b, int p) { if (b > a) { return 0; } LL te; te = (LL) num[b]; te = te * num[a - b] % p; b = (int) te; a = num[a]; int d = gcd(a, b); a /= d, b /= d; te = (LL) a; extend_gcd(b, p); x = (x % p + p) % p; return (int) (te * x % p); } void solve(LL n, LL m, int p) { LL ans; int a, b; ans = 1; while (n || m) { a = n % p, b = m % p; ans = ans * C(a, b, p) % p; n /= p, m /= p; } printf("%I64d\n", ans); } int main() { #ifndef ONLINE_JUDGE freopen("t.txt", "r", stdin); #endif int T, p; LL n, m; while (scanf("%d", &T) != EOF) { while (T--) { scanf("%I64d %I64d %d", &n, &m, &p); init(p); solve(n + m, m, p); } } return 0; }
方法二:
#include<stdio.h> #define LL long long #define nnum 100001 int num[nnum], x, y; void init(int p) { int i; LL te; num[0] = 1; for (i = 1; i <= p; i++) { te = (LL) i; te = te * num[i - 1] % p; num[i] = (int) te; } } int modular_exp(int a, int b, int c) { LL res, te; res = 1, te = a % c; while (b) { if (b & 1) { res = res * te % c; } te = te * te % c; b >>= 1; } return (int) res; } int C(int a, int b, int p) { if (b > a) { return 0; } LL te; te = (LL) num[b]; te = te * num[a - b] % p; b = te; te = num[a]; return (int) (te * modular_exp(b, p - 2, p) % p); } void solve(LL n, LL m, int p) { LL ans; int a, b; ans = 1; while (n || m) { a = n % p, b = m % p; ans = ans * C(a, b, p) % p; n /= p, m /= p; } printf("%I64d\n", ans); } int main() { #ifndef ONLINE_JUDGE freopen("t.txt", "r", stdin); #endif int T, p; LL n, m; while (scanf("%d", &T) != EOF) { while (T--) { scanf("%I64d %I64d %d", &n, &m, &p); init(p); solve(n + m, m, p); } } return 0; }
fzu 2020
#include<stdio.h> #define LL long long int modular_exp(int a, int b, int c) { LL res, te; te = a % c, res = 1; while (b) { if (b & 1) { res = res * te % c; } te = te * te % c; b >>= 1; } return (int) res; } int C(int n, int m, int p) { if (m > n) { return 0; } int i; LL res, a, b; res = 1, a = 1, b = 1; for (i = 0; i < m; i++) { a = a * (n - i) % p, b = b * (m - i) % p; } res = res * a * modular_exp(b, p - 2, p) % p; return (int) res; } void solve(int n, int m, int p) { LL ans; int a, b; ans = 1; while (n || m) { a = n % p, b = m % p; ans = ans * C(a, b, p) % p; n /= p, m /= p; } printf("%I64d\n", ans); } int main() { #ifndef ONLINE_JUDGE freopen("t.txt", "r", stdin); #endif int T, m, n, p; while (scanf("%d", &T) != EOF) { while (T--) { scanf("%d %d %d", &n, &m, &p); solve(n, m, p); } } return 0; }
#include<stdio.h> #include<math.h> #include<string.h> #define LL long long #define nmax 200001 int prime[nmax], flag[nmax], plen; void init() { memset(flag, -1, sizeof(flag)); int i, j; for (i = 2, plen = 0; i < nmax; i++) { if (flag[i]) { prime[plen++] = i; } for (j = 0; (j < plen) && (i * prime[j] < nmax); j++) { flag[i * prime[j]] = 0; if ((i % prime[j]) == 0) { break; } } } } int modular_exp(int a, int b, int c) { LL res, te; res = 1, te = a % c; while (b) { if (b & 1) { res = res * te % c; } te = te * te % c; b >>= 1; } return res; } int getNum(int n, int m) { int res; res = 0; while (n) { res += n / m; n /= m; } return res; } void solve(int a, int b, int c) { int i, te; LL res; for (i = 0, res = 1; (i < plen) && (prime[i] <= a); i++) { te = getNum(a, prime[i]) - getNum(b, prime[i]) - getNum(a - b, prime[i]); res = res * modular_exp(prime[i], te, c) % c; } printf("%lld\n", res); } int main() { #ifndef ONLINE_JUDGE freopen("t.txt", "r", stdin); #endif init(); int t, a, b, c, i; while (scanf("%d", &t) != EOF) { for (i = 1; i <= t; i++) { scanf("%d %d %d", &a, &b, &c); solve(a + b - 2, b - 1, c); } } return 0; }
hrbeu 组合数
#include<stdio.h> #include<math.h> #include<string.h> #define LL long long #define nmax 100001 int prime[nmax], flag[nmax], plen; void init() { memset(flag, -1, sizeof(flag)); int i, j; for (i = 2, plen = 0; i < nmax; i++) { if (flag[i]) { prime[plen++] = i; } for (j = 0; (j < plen) && (i * prime[j] < nmax); j++) { flag[i * prime[j]] = 0; if ((i % prime[j]) == 0) { break; } } } } int modular_exp(int a, int b, int c) { LL res, te; res = 1, te = a % c; while (b) { if (b & 1) { res = res * te % c; } te = te * te % c; b >>= 1; } return res; } int getNum(int n, int m) { int res; res = 0; while (n) { res += n / m; n /= m; } return res; } int getMin(int a, int b) { return (a > b ? b : a); } void solve(int a, int b, int c) { int i, te; LL res; for (i = 0, res = 1; (i < plen) && (prime[i] <= a); i++) { te = getNum(a, prime[i]) - getNum(b, prime[i]) - getNum(a - b, prime[i]); res = res * modular_exp(prime[i], te, c) % c; } printf("%lld\n", res); } int main() { #ifndef ONLINE_JUDGE freopen("t.txt", "r", stdin); #endif init(); int t, a, b, c, i; while (scanf("%d", &t) != EOF) { for (i = 1; i <= t; i++) { scanf("%d %d %d", &a, &b, &c); solve(a + b, getMin(a, b), c); } } return 0; }
fzu 1564
#include<stdio.h> #include<string.h> #define nmax 1000001 int prime[nmax], flag[nmax], plen, mark; void init() { memset(flag, -1, sizeof(flag)); int i, j; for (i = 2, plen = 0; i < nmax; i++) { if (flag[i]) { prime[plen++] = i; } for (j = 0; (j < plen) && (i * prime[j] < nmax); j++) { flag[i * prime[j]] = 0; if (i % prime[j] == 0) { break; } } } } int getNum(int n, int m) { int res; res = 0; while (n) { res += n / m; n /= m; } return res; } /* int getNum(int n, int m) { int res; res = 0; while (n) { res += n % m; n /= m; } return res; } */ void solve(int a, int b, int c) { int i, cnt, te; for (i = 0; (i < plen) && (prime[i] <= c); i++) { if (c % prime[i] == 0) { cnt = 0; while (c % prime[i] == 0) { c /= prime[i]; cnt++; } te = getNum(a, prime[i]) - getNum(b, prime[i]) - getNum(a - b, prime[i]); if (te < cnt) { mark = 1; return; } /*te = -getNum(a, prime[i]) + getNum(b, prime[i]) + getNum(a - b, prime[i]); if (te / (prime[i] - 1) < cnt) { mark = 1; return; }*/ } } if (mark && (c > 1)) { te = getNum(a, prime[i]) - getNum(b, prime[i]) - getNum(a - b, prime[i]); if (te < cnt) { mark = 1; return; } /*te = -getNum(a, c) + getNum(b, c) + getNum(a - b, c); if (te / (c - 1) < cnt) { mark = 1; return; }*/ } } int main() { #ifndef ONLINE_JUDGE freopen("t.txt", "r", stdin); #endif int t, a, b, c; init(); while (scanf("%d", &t) != EOF) { while (t--) { scanf("%d %d %d", &a, &b, &c); mark = 0; solve(a, b, c); if (mark) { puts("No"); } else { puts("Yes"); } } } return 0; }