题意:
求组合数 C(n,m)
思路:
我们知道 C(n,m) = (n!) / (m! * (n-m)!)
但是这里的 n m 都很大,而且需要对 mod 取模,所以需要用到 逆元处理分数取模问题
求逆元可以用扩展欧几里得算法或者费马小定理(快速幂)算法;
这里是用到的是 有费马小定理推出来 运用快速幂:
费马小定理: a ^ (m - 1) % ( m ) 恒等于 1
可以推出:(a) * (a ^(m-2)) % m = 1; 并且有: (a)*(1/a) % m = 1;
所以 (1/a)% m = ( a ^ ( m-2 ) ) % m;
也就是说 a ^ ( m - 2) 是 a 对于m取模的 逆元;
ac代码如下:
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 7, maxd = 1e6 + 7;
const ll mod = 1000003;
int n, m;
ll f[maxn];
void init() {
f[0] = 1;
for(int i = 1; i <= mod; ++i) {
f[i] = (f[i-1] * i) % mod;
}
}
ll pow(ll a, ll b) {
ll res = 1;
while(b) {
if(b & 1) res = (res * a) % mod;
a = (a * a) % mod;
b /= 2;
}
return res;
}
ll lucas() {
ll res = 1;
int a = n%mod, b = m%mod;
res = ( res * f[a] * pow(f[b] * f[a-b] % mod, mod-2) ) % mod;
return res;
}
int main() {
init();
int T;
scanf("%d", &T);
for(int tt = 1; tt <= T; ++tt) {
scanf("%d %d", &n, &m);
ll ans = lucas();
printf("Case %d: %d\n", tt, ans);
}
return 0;
}