LightOJ - 1067 Combinations(快速幂+逆元)

来源:互联网 发布:淘宝客好做不 编辑:程序博客网 时间:2024/05/18 22:16

Description

Given n differentobjects, you want to take k of them. How many ways to can do it?

 

For example, saythere 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 withan integer T (≤ 2000), denoting the number of test cases.

 

Each test casecontains 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 verylarge, you have to print the result modulo 1000003.

 

Sample Input

3

4 2

5 0

6 4

Sample Output

Case 1: 6

Case 2: 1

Case 3: 15


题意:求组合数C(n,k)%1000003的结果

分析:根据公式C(n,k)=n!/((n-k)!*k!),可以先求出n!,(n-k)!和k!,利用费马小定理分别求出(n-k)!和k!的逆元:(1/(n-k)!)%mod=((n-k)!)^(mod-2)%mod,k!%mod=(k!)^(mod-2),然后即可得出结果。需要注意的是为了防止TLE需要预处理计算出1000000内的阶乘。下面附上AC代码


#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>using namespace std;typedef long long ll;const int maxn=1000005;const int mod=1000003;ll jie[maxn];int n,k;void f()      //预处理求出1000000内阶乘,防TLE{    jie[0]=1;    for(ll i=1;i<=1000000;i++)        jie[i]=(jie[i-1]*i)%mod;}int pow_mod(int a,int n,int m)  //快速幂计算a^n%m{    if(n==0) return 1;    int x=pow_mod(a,n/2,m);    ll ans=(ll)x*x%m;    if(n%2) ans=ans*a%m;    return (int)ans;}int main(){    int T;    scanf("%d",&T);    int cnt=1;    f();    while(~scanf("%d%d",&n,&k))    {        if(k==0||k==n)        {            printf("Case %d: 1\n",cnt++);            continue;        }        if(k>n/2) k=n-k;        int p1=(int)jie[n],p2=(int)jie[n-k],p3=(int)jie[k];        p2=pow_mod(p2,mod-2,mod);   p3=pow_mod(p3,mod-2,mod); //计算逆元        ll ans=((ll)p1*p2)%mod*p3%mod;        printf("Case %d: %d\n",cnt++,(int)ans);    }    return 0;}


0 0
原创粉丝点击