10
12
2016
0

[BZOJ2982] combination

手残忘了算0的逆元了……算到1就停了然后就挂了

其实这只是一个预处理阶乘逆元+Lucas定理算组合数的故事

设要算的取模的组合数为$Lucas(n,m)$

$Lucas(n,m)=Lucas(n/P,m/P)*C(n\%P,m\%P)\%P$ 其中P为取模的质数

其实P也可以不是质数,不过那样就要用中国剩余定理合并比较麻烦了

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const long long P=10007;

long long test,n,m,fac[P+3],frac[P+3];

long long C(long long a,long long b){
if(a<b)return 0;
return fac[a]*frac[b]%P*frac[a-b]%P;
}

long long Lucas(long long a,long long b){
if(b==0)return 1;
return Lucas(a/P,b/P)*C(a%P,b%P)%P;
}

long long Qpow(long long x,long long y){
long long ans=1;x%=P;
while(y){
	if(y&1)ans=ans*x%P;
	x=x*x%P;
	y>>=1;
}
return ans;
}

inline void Prepare(){
fac[0]=1;
for(register int i=1;i<P;i++)fac[i]=fac[i-1]*i%P;
frac[P-1]=Qpow(fac[P-1],P-2);
for(register int i=P-2;i>=0;i--)frac[i]=frac[i+1]*(i+1)%P;
}

int main(){
freopen("2982.in","r",stdin);
freopen("2982.out","w",stdout);
scanf("%lld",&test);
Prepare();
while(test--){
    scanf("%lld %lld",&n,&m);
    printf("%lld\n",Lucas(n,m));
}
return 0;
}
Category: BZOJ | Tags: bzoj OI | Read Count: 666

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com