0
点赞
收藏
分享

微信扫一扫

2015 ICL, Finals, Div. 1 Ceizenpok’s formula(组合数取模,扩展lucas定理+中国剩余定理)




J. Ceizenpok’s formula



time limit per test



memory limit per test



input



output



nk and m, and its value is a number of k-combinations of a set of n modulo m.

While the whole Universe is trying to guess what the formula is useful for, we need to automate its calculation.



Input



nkm, separated with spaces (1 ≤ n ≤ 1018, 0 ≤ k ≤ n, 2 ≤ m ≤ 1 000 000).



Output



nkm.



Sample test(s)



input



2 1 3



output



2



input



4 2 5



output



1




评测链接:​​http://codeforces.com/gym/100633/problem/J​​

解析:首先,将m做质因数分解:m=p1*p2*p3。。。。(pi=ai^ti)

      然后用扩展lucas定理求解:b[i]=c(n,m)%pi

      然后用中国剩余定理进行合并,即可得解。

代码:


#include<cstdio>
using namespace std;

typedef long long LL;

LL pow_mod(LL x,LL y,LL p)
{
LL ans=1;
while(y>0)
{
if(y&1)ans=ans*x%p;
x=x*x%p,y>>=1;
}
return ans;
}

LL c1(LL n,LL p,LL pk)
{
if(n==0)return 1;
LL i,j,k,ans=1;
for(i=2;i<=pk;i++)if(i%p)ans=ans*i%pk;
ans=pow_mod(ans,n/pk,pk);
for(k=n%pk,i=2;i<=k;i++)if(i%p)ans=ans*i%pk;
return ans*c1(n/p,p,pk)%pk;
}

LL reverse(LL a,LL m)
{
if(a==0)return 0;
LL y=0,x=1,r=a%m,q,t,mm=m;
if(r<0)r+=m;
while((m%r)!=0)
{
a=m,m=r,q=a/m,r=a%m;
t=x,x=y-x*q,y=t;
}
if(r!=1)return 0;
if(x<0)x+=mm;
return x;
}

LL cal(LL n,LL m,LL p,LL pi,LL pk)
{
LL i,j,k=0,a,b,c,ans;
a=c1(n,pi,pk),b=c1(m,pi,pk),c=c1(n-m,pi,pk);
for(i=n;i;i/=pi)k+=i/pi;
for(i=m;i;i/=pi)k-=i/pi;
for(i=n-m;i;i/=pi)k-=i/pi;
ans=a*reverse(b,pk)%pk*reverse(c,pk)%pk*pow_mod(pi,k,pk)%pk;
return ans*(p/pk)%p*reverse(p/pk,pk)%p;
}

int main()
{
LL n,m,p,ans=0,x,i,j,k;
scanf("%I64d%I64d%I64d",&n,&m,&p);
for(x=p,i=2;x>1;i++)if(x%i==0)
{
for(k=1;x%i==0;x/=i)k*=i;
ans=(ans+cal(n,m,p,i,k))%p;
}
printf("%I64d\n",ans);
}


  

举报

相关推荐

0 条评论