P4720 【模板】擴充套件盧卡斯
阿新 • • 發佈:2021-01-12
技術標籤:數學
題意:
題解:
存個模板,借用了別人的程式碼,好長學不來
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll qpow(ll a,ll b,ll mod){ll ans=1;for(;b;b>>=1,a=a*a%mod)if(b&1)ans=ans*a%mod;return ans;}
ll qpow(ll a,ll b){ll ans=1;for(;b;b>>=1,a=a*a)if(b&1)ans=ans*a;return ans;}
ll ex_gcd(ll a,ll b,ll& x,ll& y){
if(!b){
x=1,y=0;
return a;
}
else {
ll v=ex_gcd(b,a%b,y,x);
y=y-a/b*x;
return v;
}
}
bool modular(ll a[],ll m[],ll k)
{
ll d,t,c,x,y,i;
for(i=2;i<=k;i++)
{
d=ex_gcd(m[1],m[i] ,x,y);
c=a[i]-a[1];
if(c%d) return 0;
t=m[i]/d;
x=(c/d*x%t+t)%t;
a[1]=m[1]*x+a[1];
m[1]=m[1]*m[i]/d;
}
return 1;
}
ll inv(ll a,ll b)
{
ll x,y;
ex_gcd(a,b,x,y);
return (x%b+b)%b;
}
ll C(ll n,ll m,ll mod)
{
if(m>n) return 0;
ll ans= 1,i,a,b;
for(i=1;i<=m;i++)
{
a=(n+1-i)%mod;
b=inv(i%mod,mod);
ans=ans*a%mod*b%mod;
}
return ans;
}
ll C1(ll n,ll m,ll mod)
{
if(m==0) return 1;
return C(n%mod,m%mod,mod)*C1(n/mod,m/mod,mod)%mod;
}
ll cal(ll n,ll p,ll t)
{
if(!n) return 1;
ll x=qpow(p,t),i,y=n/x,temp=1;
for(i=1;i<=x;i++) if(i%p) temp=temp*i%x;
ll ans=qpow(temp,y,x);
for(i=y*x+1;i<=n;i++) if(i%p) ans=ans*i%x;
return ans*cal(n/p,p,t)%x;
}
ll C2(ll n,ll m,ll p,ll t)
{
ll x=qpow(p,t);
ll a,b,c,ap=0,bp=0,cp=0,temp;
for(temp=n;temp;temp/=p) ap+=temp/p;
for(temp=m;temp;temp/=p) bp+=temp/p;
for(temp=n-m;temp;temp/=p) cp+=temp/p;
ap=ap-bp-cp;
ll ans=qpow(p,ap,x);
a=cal(n,p,t);
b=cal(m,p,t);
c=cal(n-m,p,t);
ans=ans*a%x*inv(b,x)%x*inv(c,x)%x;
return ans;
}
//計算C(n,m)%mod
ll ex_lucas(ll n,ll m,ll mod)
{
ll i,t,cnt=0;
ll A[205],M[205];
for(i=2;i*i<=mod;i++) if(mod%i==0)
{
t=0;
while(mod%i==0)
{
t++;
mod/=i;
}
M[++cnt]=qpow(i,t);
if(t==1) A[cnt]=C1(n,m,i);
else A[cnt]=C2(n,m,i,t);
}
if(mod>1)
{
M[++cnt]=mod;
A[cnt]=C1(n,m,mod);
}
modular(A,M,cnt);
return A[1];
}
int main(){
ll n,m,mod;
scanf("%lld%lld%lld",&n,&m,&mod);
printf("%lld\n",ex_lucas(n,m,mod));
}