首先有
因为m<=n,所以n!一定是m!的倍数,在[1,m!]中于m!互质的数个数为phi[m!],在[m!+1,n!]中根据可知有(n!-m!)/m!个
所以答案为
因为,其中pi是m!的质因子,所以答案是
,pi是m!的质因子
其中m!的质因子就是m的质因子
还要预处理出pi的逆元,可以递推,公式ine[i]=(mod-mod/i*ine[mod%i]%mod);
离线处理即可,神犇说卡常数然而我并没有卡QwQ
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=10000010;
int T,mod,p[1000010],ine[maxn];
struct ques{int n,m;}q[10010];
int jc[maxn],mxn,mxm,ret[maxn],N=0;
bool vis[maxn];
int main(){
scanf("%d%d",&T,&mod); jc[1]=ine[1]=ret[1]=1;
for (int i=1;i<=T;++i)
scanf("%d%d",&q[i].n,&q[i].m),
mxn=max(mxn,q[i].n),mxm=max(mxm,q[i].m);
for (int i=2;i<=mxn;++i) jc[i]=1LL*jc[i-1]*i%mod;
for (int i=2;i<=mxm;++i){
if (!vis[i]) p[++N]=i;
for (int j=1;p[j]*i<=mxm&&j<=N;++j){
vis[p[j]*i]=1;
if (i%p[j]==0) break;
}
}
for (int i=2;i<=mxm&&i<mod;++i)
ine[i]=(mod-1LL*mod/i*ine[mod%i]%mod);
for (int i=2;i<=mxm;++i){
ret[i]=ret[i-1];
if (!vis[i]) ret[i]=1LL*ret[i]*(i-1)%mod*ine[i%mod]%mod;
}
for (int i=1;i<=T;++i)
printf("%d\n",1LL*jc[q[i].n]*ret[q[i].m]%mod);
}