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 |
费小马定理求逆元
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)
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e6+5,mod=1000003;
typedef long long LL;
LL fact[maxn];//不明白为什么这里我用define定义maxn就不行
void f()//打出阶乘表
{
fact[1]=fact[0]=1;
for(LL i=2;i<maxn;i++)
fact[i]=(i*fact[i-1])%mod;
}
LL niyuan(LL a,LL p)//快速幂
{
LL res=1%mod;
LL t=a%mod;
while(p)
{
if(p%2)
res=res*t%mod;
t=t*t%mod;
p=p/2;
}
return res;
}
LL c(int n,int k)
{
LL fm=(fact[k]*fact[n-k])%mod;
LL ans1=niyuan(fm,mod-2);//费马小定理,求一个幂就好;
return (ans1*fact[n])%mod;
}
int main()
{
int t,n,k,kase=0;
f();
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
if(k*2>n)
k=n-k;//组合数对称性,减少计算;
printf("Case %d: %lld\n",++kase,c(n,k));
}
return 0;
}