学了这么久Lucas定理,终于见到有用的时候啦
Lucas定理是处理计算组合数取模的一种算法
只有当模的数很小的时候才适用!!
此外要求模的数是质数(这么看看好像只有10007了)
具体就是一个公式: C( n , m ) % p = C ( n % p , m % p ) * C ( n / p , m / p )
按照上面的公式递归就好啦
注意当n<m时返回0
#include <iostream>
#include <cstdio>
#define mod 10007
using namespace std;
typedef long long LL;
LL jc[10050];
LL qpow(LL a,LL b) {
if (b == 0) return 0LL;
if (b == 1) return a;
if (b % 2 == 0) {
LL tmp = qpow(a,b/2);
return (tmp * tmp) % mod;
} else {
LL tmp = qpow(a,b-1);
return (a*tmp) % mod;
}
}
LL Lucas(LL n,LL m) {
if (n < m) return 0;
if (n < mod && m < mod) {
LL tmp = ( jc[n] * qpow( (jc[m] * jc[n-m])%mod , mod - 2 ) ) % mod;
return tmp;
}
LL p1 = Lucas(n % mod , m % mod) % mod;
LL p2 = Lucas(n / mod , m / mod) % mod;
return (p1 * p2) % mod;
}
int main() {
int T = 0;
scanf("%d",&T);
jc[0] = 1LL;
for (int i=1;i<=mod;i++) jc[i] = (jc[i-1] * i) % mod;
while (T--) {
LL n,m;
scanf("%lld%lld",&n,&m);
LL ans = Lucas(n,m);
printf("%lld\n",ans);
}
return 0;
}