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

本文介绍了一种计算组合数C(n,k)的方法,并通过快速幂运算来求解大数阶乘及其逆元,最终得到C(n,k)%1000003的结果。通过预处理方式避免了超时问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值