记录编号 457054 评测结果 AAAAAAAAAAA
题目名称 [HZOI 2015] 组合数取模 最终得分 100
用户昵称 GravatarCSU_Turkey 是否通过 通过
代码语言 C++ 运行时间 0.118 s
提交时间 2017-10-06 16:39:03 内存使用 0.31 MiB
显示代码纯文本
#include<bits/stdc++.h>//费马小定理p必须为素数,欧拉定理还要求欧拉函数,而exgcd只要两数互质即可,在本题更适用 
#define ll long long
using namespace std;
ll n,m,p,ans;
ll gcd(ll a,ll b,ll &x,ll &y){
	if(!b){
		x=1;y=0;return a;
	}
	ll t=gcd(b,a%b,x,y);
	ll tem=x;x=y;y=tem-(a/b)*y;return t;
}
ll inv(ll a,ll b){
	ll x,y;gcd(a,b,x,y);if(x<0)x+=b;return x;
}
ll fast(ll x,ll y,ll z){
	ll ans=1;
	while(y){
		if(y&1)ans*=x,ans%=z;
		x=x*x%z;y>>=1;
	}return ans;
}
ll C(ll x,ll pi,ll pk){
	if(!x)return 1;
	ll ans=1,ans2=1;
	for(int i=1;i<=pk;i++)if(i%pi)ans=ans*i%pk;
	for(int i=1;i<=x/pk;i++)ans2=ans2*ans%pk;
	for(int i=1;i<=x%pk;i++)if(i%pi)ans2=ans2*i%pk;//开始忘了加i%pi...还过了除mike新加的以外的点... 
	return ans2*C(x/pi,pi,pk)%pk;//qwq没加取模 
}
ll lucas(ll x,ll y,ll pi,ll pk){//逆元解决不了的啊...pk不一定与c互质 
	ll tem1=C(x,pi,pk);
	ll tem2=C(y,pi,pk);
	ll tem3=C(x-y,pi,pk);
	ll k=0;
	for(int i=x;i;i/=pi)k+=i/pi;
	for(int i=y;i;i/=pi)k-=i/pi;
	for(int i=x-y;i;i/=pi)k-=i/pi;
	return tem1%pk*fast(pi,k,pk)%pk*inv(tem2,pk)%pk*inv(tem3,pk)%pk;
}
int main()
{
	freopen("combinatorial_mod.in","r",stdin);
	freopen("combinatorial_mod.out","w",stdout);
	scanf("%lld%lld%lld",&n,&m,&p);
	ll tem=p;
	for(int i=2;i*i<=tem;i++){
		if(tem%i)continue;
		ll pk=1;
		while(tem%i==0)pk*=i,tem/=i;
		ans+=inv(p/pk,pk)*(p/pk)%p*lucas(n,m,i,pk)%p;ans%=p;
	}
	if(tem!=1)ans+=inv(p/tem,tem)%p*(p/tem)%p*lucas(n,m,tem,tem);
	cout<<ans%p;
	return 0;
}