[國家集訓隊] 禮物
Description
給定P,求\(\Pi_{i=1}^m C_{n-w_1-w_2-...-w_{i-1}}^{w_i}\;mod\;P\) 。\(m\leq 5\) 。
Solution
擴充套件Lucas的板子。
P不是質數的話可以先質因數分解,然後求出同餘每個質數次冪的解,再CRT合併就吼了
\(n!\)怎麼求還是注意一下吧,要先把和
\(p_i\)
不互質的部分拎出來算。拎出來的程式碼大概就是這樣
for(int i=n;i;i/=c[cur]) now+=i/c[cur];
別的就沒啥了。突然發現自己數論忘了好多,都是看的自己之前寫的部落格。
Code
#include<cmath> #include<cctype> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using std::min; using std::max; using std::swap; #define int long long int p[100005],c[100005]; int P,w[10],tot,a[100005]; int exgcd(int a,int b,int &x,int &y){ if(!b){ x=1,y=0; return a; } int d=exgcd(b,a%b,y,x); y-=a/b*x;return d; } int inv(int a,int b){ int x,y; exgcd(a,b,x,y); return (x%b+b)%b; } int getint(){ int X=0,w=0;char ch=0; while(!isdigit(ch))w|=ch=='-',ch=getchar(); while( isdigit(ch))X=X*10+ch-48,ch=getchar(); return w?-X:X; } int ksm(int a,int b,int c){ int ans=1; while(b){ if(b&1) ans=ans*a%c; a=a*a%c;b>>=1; } return ans; } void fj(int P){ int sq=sqrt(P); for(int i=2;i<=sq;i++){ if(P%i==0){ c[++tot]=i; while(P%i==0) p[tot]++,P/=i; p[tot]=ksm(i,p[tot],1e9+2); } } if(P!=1) c[++tot]=P,p[tot]=P; } int solve(int x,int cur){ if(!x) return 1; int now=1; for(int i=2;i<p[cur];i++){ if(i%c[cur]) now=now*i%p[cur]; } now=ksm(now,x/p[cur],p[cur]); int q=x%p[cur]; for(int i=2;i<=q;i++){ if(i%c[cur]) now=now*i%p[cur]; } return now*solve(x/c[cur],cur)%p[cur]; } int C(int n,int m,int cur){ if(n<m) return 0; if(n==m) return 1; int now=0; for(int i=n;i;i/=c[cur]) now+=i/c[cur]; for(int i=m;i;i/=c[cur]) now-=i/c[cur]; for(int i=n-m;i;i/=c[cur]) now-=i/c[cur]; int a=solve(n,cur),b=solve(m,cur),cc=solve(n-m,cur); return a*inv(b,p[cur])%p[cur]*inv(cc,p[cur])%p[cur]*ksm(c[cur],now,p[cur])%p[cur]; } int CRT(){ int ans=0; for(int i=1;i<=tot;i++) ans=(ans+a[i]*(P/p[i])*inv(P/p[i],p[i]))%P; return ans; } signed main(){ P=getint();fj(P); int n=getint(),m=getint(),cnt=0; for(int i=1;i<=m;i++) w[i]=getint(),cnt+=w[i]; if(cnt>n) return printf("Impossible"),0; int ans=1,sum=n; for(int i=1;i<=m;i++){ for(int j=1;j<=tot;j++) a[j]=C(sum,w[i],j); // printf("CRT=%lld\n",CRT()); ans=ans*CRT()%P; sum-=w[i]; } printf("%lld\n",ans); return 0; }