Given n different objects, you want to take kof them. How many ways to can do it?
For example, say there are 4 items; you want to take 2 ofthem. 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 |
Problem Setter: Jane Alam Jan
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
const int mod=1e6+3;
ll f[maxn];
/*
费马小定理求逆元
a/b=1mod( M );
只要 M 是一个素数,而且 b 不是 M 的倍数,就可以用一个逆元整数 b’,通过 a/b=a*b'*(mod M)来以乘换除
费马小定理说,对于素数 M 任意不是 M 的倍数的 b,都有:b^(M-1)=1 (mod) M;
于是可以拆成:b*b^(M-2)=1(mod)M;
所以:a/b=a/b*(b*b^(M-2))=a*(b^(M-2))(mod M)
也就是说我们要求的逆元就是b^(M-2)(mod M)
*/
void init(){
f[1]=f[0]=1;
for(int i=2;i<maxn;i++){
f[i]=(f[i-1]*i)%mod;
}
}
ll get_niyuan(ll base,int n){
ll ans=1;
while(n){
if(n&1){
ans=(ans*base)%mod;
}
base=(base*base)%mod;
n/=2;
}
return ans;
}
ll C(int n,int k){
ll ans=(f[k]*f[n-k])%mod;
ans=get_niyuan(ans,mod-2);
return (ans*f[n])%mod;
}
int main(){
init();
int T,kase=1;
scanf("%d",&T);
while(T--){
int n,k;
scanf("%d %d",&n,&k);
if(2*k>n)//减小运算的次数
k=n-k;
printf("Case %d: %lld\n",kase++,C(n,k));
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
const int mod=1e6+3;
ll f[maxn];
/*
费马小定理求逆元
a/b=1mod( M );
只要 M 是一个素数,而且 b 不是 M 的倍数,就可以用一个逆元整数 b’,通过 a/b=a*b'*(mod M)来以乘换除
费马小定理说,对于素数 M 任意不是 M 的倍数的 b,都有:b^(M-1)=1 (mod) M;
于是可以拆成:b*b^(M-2)=1(mod)M;
所以:a/b=a/b*(b*b^(M-2))=a*(b^(M-2))(mod M)
也就是说我们要求的逆元就是b^(M-2)(mod M)
首先,Lucas(卢卡斯)定理是什么?有什么用?
Lucas定理是用来求 C(n,m) mod p,p为素数的值。(注意:p一定是素数)
有人会想,C(n,m)不能用C(n, m) = C(n - 1,m) + C(n - 1, m - 1)的公式来递推吗?
( 提示:C(n, m) mod p = n!/(m!(n - m)!) mod p )
可以是可以。但当n,m,p都很大时,你递推所用的时间就会很爆炸了。所以,这就需要用到Lucas定理来解决了。
因此,Lucas定理用来解决大组合数求模是很有用的。
注意:Lucas定理最大的数据处理能力是p在10^5左右,不能再大了。再大的话,我就不知道le
表达式:C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p。(可以递归)
递归方程:Lucas(n,m)=(C(n%p, m%p)*Lucas(n/p, m/p))%p。(递归出口为m==0,return 1)
*/
void init(){
f[1]=f[0]=1;
for(int i=2;i<maxn;i++){
f[i]=(f[i-1]*i)%mod;
}
}
ll get_niyuan(ll base,int n){
ll ans=1;
while(n){
if(n&1){
ans=(ans*base)%mod;
}
base=(base*base)%mod;
n/=2;
}
return ans;
}
ll C(int n,int k){
ll ans=(f[k]*f[n-k])%mod;
ans=get_niyuan(ans,mod-2);
return (ans*f[n])%mod;
}
ll Lucas(int n,int m){
return m==0?1:(C(n%mod,m%mod)*Lucas(n/mod,m/mod))%mod;
}
int main(){
init();
int T,kase=1;
scanf("%d",&T);
while(T--){
int n,k;
scanf("%d %d",&n,&k);
if(2*k>n)//减小运算的次数
k=n-k;
printf("Case %d: %lld\n",kase++,Lucas(n,k));
}
return 0;
}