右边的部分,把pi因子提出来后,发现又是阶乘的形式,所以我们可以递归来解决了。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<iostream> using namespace std; int seq[50],tot,mod[50],inv[50]; long long sum[50]; int n,m; long long Mod; int fac[50][100010]; int w[10]; long long ans=1; long long power(long long x,int y,int mod) { long long ans=1; while (y) { if (y&1) ans=ans*x%mod; x=x*x%mod; y>>=1; } return ans; } void decompose() { long long n=Mod; for (int i=2;(long long)i*i<=n;i++) if (n%i==0) { seq[++tot]=i;mod[tot]=1; while (n%i==0) mod[tot]*=i,n/=i; } if (n!=1) seq[++tot]=n,mod[tot]=n; } int cal(int x,int i)//除掉seq[i]因子的x!%mod[i]的值 { int ans=1; if (x<seq[i]) ans=fac[i][x]; else { ans=power(fac[i][mod[i]-1],x/mod[i],mod[i]); ans=(long long)ans*fac[i][x%mod[i]]%mod[i]; ans=(long long)ans*cal(x/seq[i],i)%mod[i]; } return ans; } int calc(int x,int i) { int ans=0; if (x<seq[i]) return 0; else { ans+=x/seq[i]; ans+=calc(x/seq[i],i); } return ans; } int C(int x,int y,int i) { int num=calc(x,i)-calc(x-y,i)-calc(y,i); int ans=(long long)cal(x,i)*power(cal(x-y,i),mod[i]/seq[i]*(seq[i]-1)-1,mod[i])*power(cal(y,i),mod[i]/seq[i]*(seq[i]-1)-1,mod[i])*power(seq[i],num,mod[i])%mod[i]; return ans; } long long C(int x,int y) { for (int i=1;i<=tot;i++) inv[i]=C(x,y,i); long long ans=0; for (int i=1;i<=tot;i++) ans+=(long long)inv[i]*sum[i]*power(sum[i],mod[i]/seq[i]*(seq[i]-1)-1,mod[i])%Mod; return ans; } int main() { //freopen("gift.in","r",stdin); //freopen("gift.out","w",stdout); scanf("%lld%d%d",&Mod,&n,&m); long long cnt=0; for (int i=1;i<=m;i++) {scanf("%d",&w[i]);cnt+=w[i];} if (cnt>n) { printf("Impossible\n"); return 0; } decompose(); for (int i=1;i<=tot;i++) { sum[i]=Mod/mod[i]; fac[i][0]=1; for (int j=1;j<=100000;j++) if (j%seq[i]!=0) fac[i][j]=(long long)fac[i][j-1]*j%mod[i]; else fac[i][j]=fac[i][j-1]; } for (int i=1;i<=m;i++) ans=ans*C(n,w[i])%Mod,n-=w[i]; printf("%lld\n",ans); return 0; }