组合数取余
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;
}