洛咕 P2155 [SDOI2008]沙拉公主的困惑
阿新 • • 發佈:2018-11-11
洛咕 P2155 [SDOI2008]沙拉公主的困惑
有個結論,就是如果\(gcd(a,b)=1\),那麼\(gcd(a+kb,b)=1\)。證明比較顯然。
所以這個題目要問的\(n!\)就可以分成\(\frac{n!}{m!}\)段,每一段和\(m!\)互質的數量都相同,那麼顯然就是\(\phi(m!)\)
所以答案是\(\frac{n!}{m!}\phi(m!)\)
然後怎麼求呢,拆開
\(\frac{n!}{m!}\phi(m!)=\frac{n!}{m!}m!\Pi\frac{p-1}{p}=n\times \Pi\frac{p-1}{p}\)
就是\(m!\)有哪些質因數,顯然就是1-m所有數質因數的並,也就是\(\Pi_{i\leq m \text{ and i is prime}}\frac{i-1}{i}\)
這兩個都可以直接預處理,就做完了。。
#include<bits/stdc++.h> #define il inline #define vd void typedef long long ll; il int gi(){ int x=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-')f=-1; ch=getchar(); } while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } int p[10000001],inv[10000001],pr[665000],d[10000001],dd[10000001]; int s[10000001]; bool yes[10000001]; int main(){ #ifndef ONLINE_JUDGE freopen("1473.in","r",stdin); freopen("1473.out","w",stdout); #endif ll T=gi(),R=gi(),n,m; for(int i=2;i<=10000000;++i){ if(!yes[i])pr[++pr[0]]=i,d[i]=dd[i]=i; for(int j=1;1ll*i*pr[j]<=10000000&&j<=pr[0];++j){ yes[i*pr[j]]=1;d[i*pr[j]]=pr[j]; if(i%pr[j]==0){ dd[i*pr[j]]=dd[i]; break; } dd[i*pr[j]]=dd[i]*pr[j]; } } p[0]=1;for(int i=1;i<=10000000;++i)p[i]=1ll*p[i-1]*i%R; inv[1]=1;for(int i=2;i<R&&i<=10000000;++i)inv[i]=(R-1ll*(R/i)*inv[R%i]%R)%R; for(int i=1;i<=pr[0];++i)s[pr[i]]=1ll*(pr[i]-1)*inv[pr[i]]%R; s[1]=1; for(int i=2;i<=10000000;++i) if(s[i]==0)s[i]=s[i-1]; else s[i]=1ll*s[i]*s[i-1]%R; while(T--){ n=gi(),m=gi(); if(n>R)puts("0"); else printf("%lld\n",1ll*p[n]*s[m]%R); } return 0; }