BZOJ2186 SDOI2008沙拉公主的困惑(数论)
由于n!是m!的倍数,而对于每个与m!互质且小于m!的数x,x+m!、x+2*m!……也与其互质,所以答案即为(n!/m!)*φ(m!)。
φ(m!)=m!*∏(1-1/pi)。其中的pi即为1~m中所有质数。那么这个前缀积就可以预处理了。
当n、m大于p的时候是可能有问题的,数据里没有就懒得讨论了。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 10000010 int T,P,prime[N],exphi[N],cnt=0; int fac[N],inv[N],inv2[N]; bool flag[N]; int main() { #ifndef ONLINE_JUDGE freopen("bzoj2186.in","r",stdin); freopen("bzoj2186.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif T=read(),P=read(); fac[0]=1;for (int i=1;i<min(P,N-9);i++) fac[i]=1ll*fac[i-1]*i%P; inv[1]=1;for (int i=2;i<min(P,N-9);i++) inv[i]=(P-1ll*(P/i)*inv[P%i]%P)%P; inv2[1]=1;for (int i=2;i<min(P,N-9);i++) inv2[i]=1ll*inv2[i-1]*inv[i]%P; flag[1]=1; for (int i=2;i<min(P,N-9);i++) { if (!flag[i]) prime[++cnt]=i; for (int j=1;j<=cnt&&prime[j]*i<=N-10;j++) { flag[prime[j]*i]=1; if (i%prime[j]==0) break; } } exphi[1]=1; for (int i=2;i<min(P,N-9);i++) if (!flag[i]) exphi[i]=1ll*exphi[i-1]*(P+1-inv[i])%P; else exphi[i]=exphi[i-1]; for (int i=1;i<min(P,N-9);i++) exphi[i]=1ll*exphi[i]*fac[i]%P; while (T--) { int n=read(),m=read(); printf("%d\n",1ll*fac[n]*inv2[m]%P*exphi[m]%P); } return 0; }