RT,一直WA on test#10,13,16,17,19
题解第二篇枚举了 1∼m 显然直接 1018 了,我用了两次 exlucas 求。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<ctime>
#include<cmath>
#include<iomanip>
#include<string>
#include<cstring>
#include<set>
#include<stack>
#include<queue>
#include<bitset>
using namespace std;
namespace IO{
template<typename T>inline void read(T &x){
x=0;
char ch=getchar();
bool flag=0;
while(ch<'0'||ch>'9') flag=flag||(ch=='-'),ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+(ch^'0'),ch=getchar();
if(ch!='.'){
x=flag?-x:x;
return;
}
double Base=0.1;
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=x+Base*(ch^'0'),Base/=10.0,ch=getchar();
x=flag?-x:x;
}
template<typename T>void prt(T x){
if(x>9) prt(x/10);
putchar(x%10+'0');
}
template<typename T>inline void put(char ch,T x){
if(x<0) putchar('-'),x=-x;
prt(x);
putchar(ch);
}
const int DM[10]={1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};
inline void putd(char ch,double x,int w){
if(x<0) putchar('-'),x=-x;
if(!w){
put(ch,(int)(x+0.5));
return;
}
int prex=(int)x;
x-=(int)x;
x*=DM[w];
x+=0.5;
int nowx=(int)x,now=0;
if(nowx>=DM[w]) nowx=0,prex++;
put('.',prex);
int xx=nowx;
if(!xx) now=1;
else while(xx) xx/=10,now++;
now=w-now;
while(now--) putchar('0');
put(ch,nowx);
}
inline void putstr(string s){
for(int i=0;i<s.length();i++) putchar(s[i]);
}
}
using namespace IO;
#define ll long long
inline ll power(ll x,ll y,ll p){//快速幂
ll res=1;
while(y){
if(y&1) res=res*x%p;
x=x*x%p;
y>>=1;
}
return res;
}
inline ll exgcd(ll a,ll b,ll &x,ll &y){//扩欧
if(!b) return a+(x=1)+(y=0)-1;
ll d=exgcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
inline ll inv(ll x,ll p){//求逆元
ll a,b;
exgcd(x,p,a,b);
return (a%p+p)%p;
}
inline ll F(ll n,ll p,ll pk){//算n!/p^x mod p^k
if(!n) return 1;
ll lop=1,lst=1;
for(ll i=1;i<=pk;i++)
if(i%p) lop=lop*i%pk;
lop=power(lop,n/pk,pk);
for(ll i=(n/pk)*pk;i<=n;i++)
if(i%p) lst=lst*(i%pk)%pk;
ll res=lop*lst%pk*F(n/p,p,pk)%pk;
return res;
}
inline ll getp(ll x,ll p){//计算多少个p
if(x<p) return 0;
return getp(x/p,p)+(x/p);
}
inline ll calc(ll n,ll m,ll p,ll pk,bool type){//计算C(n,m)/A(n,m)
ll up=F(n,p,pk),down=inv(F(n-m,p,pk),pk);
if(type) down=down*inv(F(m,p,pk),pk)%pk;//排列和组合
ll nowp=power(p,getp(n,p)-getp(n-m,p)-(type?getp(m,p):0),pk);
return nowp*up%pk*down%pk;
}
#define N 107
ll a[N],b[N],cnt;
inline ll CRT(ll n,ll M){
ll ans=0;
for(int i=1;i<=n;i++){
ll nowm=M/a[i],invm=inv(nowm,a[i]);
ans=(ans+b[i]*nowm%M*invm%M)%M;
}
return ans;
}
inline ll exlucas(ll n,ll m,ll p,bool type){
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
ll now=p;
cnt=0;
for(ll i=2;i*i<=p;i++){
if(!(now%i)){
ll pk=1;
while(!(now%i)) now/=i,pk*=i;
a[++cnt]=pk;
b[cnt]=calc(n,m,i,pk,type);
}
}
if(now!=1){
a[++cnt]=now;
b[cnt]=calc(n,m,now,now,type);
}
return CRT(cnt,p);
}
ll n,m,p,ans=1;
int main(){
read(n),read(m),read(p);
ans=exlucas(n,m,p,1)*exlucas(n,m,p,0)%p;
put('\n',ans);
return 0;
}