LIGHT OJ-1067 Combinations【逆元(欧拉)+快速幂+同余】

2019-04-13 22:03发布

1067 - Combinations
PDF (English) Statistics Forum
Time Limit: 2 second(s) Memory Limit: 32 MB
Given n different objects, you want to take k of them. How many ways to can do it? For example, say there are 4 items; you want to take 2 of them. So, you can do it 6 ways. Take 1, 2
Take 1, 3
Take 1, 4
Take 2, 3
Take 2, 4
Take 3, 4 Input
Input starts with an integer T (≤ 2000), denoting the number of test cases. Each test case contains two integers n (1 ≤ n ≤ 106), k (0 ≤ k ≤ n). Output
For each case, output the case number and the desired value. Since the result can be very large, you have to print the result modulo 1000003. Sample Input
Output for Sample Input
3
4 2
5 0
6 4
Case 1: 6
Case 2: 1
Case 3: 15
  1. 题意:求c(n,K)%1000003的值;
  2. 思路:c(n,m)=A(n,m)/A(m,m)=n!/(n-m)!/m!,用此结果对1000003取余,光个阶乘指数增长就超了,应该将取余想办法放到里面,有除不能直接用同余定理,应该化除为乘求除数的逆元,根据欧拉定理:a^phi(n)=1mod(n)(a,n互质),可得a*a^[phi(n)-1]=1mod(n),就得到a关于模n的逆元是a^[phi(n)-1],注意a,n一定要互质。此题中1000003就是质数,所以他和任意数互质,即phi(n)=1000003-1,这时我们就要求n!(n-m)^[phi(n)-1] m!^[phi(n)-1] %1000003,我们发现不数大而且运算次数多,这时我们可以用一个数组a[i]保存i!%1000003,用同余定理解决,就算是打了个表,对于次方就用快速幂运算几次就解决了;
  3. 失误:就按题目中的数据类型来吧,尤其是要用ll还是__int64的时候;
  4. 代码如下:

#include #include using namespace std; const int MAXN=1e6+10;//内存还不能超 10^7就超了 #define mod 1000003 long long a[MAXN];//防止超都用ll long long quickpow(long long base,long long b,long long m)//快速幂 { long long ans=1; while(b) { if(b&1) { ans=ans*base%m; --b; } b>>=1; base=base*base%m; } return ans; } void jiecheng(long long n,long long m)//没有函数返回值 { a[0]=1;//求a[1] for(long long i=1;i<=n;++i) { a[i]=i%m*a[i-1]%m;//a[i]=i!%mod } } int main() { long long ans,t,n,m,k=0; jiecheng(MAXN,mod); scanf("%lld",&t); while(t--) { scanf("%lld %lld",&n,&m); long long ans=a[n]*quickpow(a[m],mod-2,mod)*quickpow(a[n-m],mod-2,mod)%mod; printf("Case %lld: %lld ",++k,ans);//还必须是ll __int64就是格式错 } return 0; }