题目:Combinations LightOJ - 1067
题意:有n个数,你从中拿走k个,一共有多少种可能。
思路:这道题从题意中很明显的看出这道题是组合数学,但是数据比较大,你不能把所有的结果都求出来再模上一个数,这显然是不可能的,所以需要你换一种思路,所以想到Lucas定理。通过Lucas来求解,该题。
代码:
本题用到了递归求逆元:逆元的求法总结(3种基本方法+4种实现)
#include<string.h>
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int mod = 1000003;
const int maxn = 1000100;
LL F[maxn];
void Init()//阶乘
{
F[0] = 1;//一定要从0开始初始化
for(int i = 1; i <= maxn; i++)
{
F[i] = F[i-1]*i % mod;
}
}
LL inv(LL n, LL m)//递归求逆元
{
if(n == 1)return 1;
return inv(m % n, m)*(m-m/n)%m;
}
LL Lucas(LL n, LL m, LL p)
{
LL ans = 1;
while(n && m)
{
LL a = n % p, b = m % p;
if(a < b)return 0;
ans = ans *F[a]%p*inv(F[b]*F[a-b]%p, p)%p;
n /= p;
m /= p;
}
return ans;
}
int main(){
int T;
int a, b, t;
Init();
scanf("%d", &T);
int ca = 0;
while(T--){
scanf("%d %d", &a, &b);
t = Lucas(a, b, mod);
printf("Case %d: %lld\n", ++ca, t);
}
return 0;
}