若(x,y)=1则(x+n*y,y)=1,又因为n>=m所以答案就是:
(n!)/(m!)*phi(m!)=(n!)/(m!)*(m!)*∏(1-1/p)=(n!)*∏(1-1/p)
全部预处理完事。
线推逆元inv[i]=-(Mod/i)*inv[i%Mod]%Mod
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define maxn 10000021
using namespace std;
bool vis[maxn];
int cnt,pri[maxn],inv[maxn],T,Mod,n,m,fac[maxn],p[maxn];
void make(){
inv[1]=1,fac[1]=fac[0]=1;
for(int i=2;i<maxn;i++){
fac[i]=(LL)fac[i-1]*i%Mod;
inv[i]=-((LL)Mod/i)*(LL)inv[Mod%i]%Mod;
if(inv[i]<0)inv[i]+=Mod;
if(!vis[i])pri[++cnt]=i;
for(int j=1;j<=cnt&&(LL)pri[j]*i<maxn;j++){
vis[i*pri[j]]=true;
if(i%pri[j]==0)break;
}
}
p[0]=1;
for(int i=1;i<=cnt;i++){
p[i]=((LL)p[i-1]*(1-inv[pri[i]]+Mod)%Mod+Mod)%Mod;
}
}
int main(){
scanf("%d%d",&T,&Mod);
make();int ans;
while(T--){
scanf("%d%d",&n,&m);
ans=(LL)fac[n]*p[upper_bound(pri+1,pri+1+cnt,m)-pri-1]%Mod;
printf("%d\n",ans);
}
return 0;
}