线性筛。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 10000050 using namespace std; int t,mod,n,m,fac[maxn],prime[maxn],top=0,f1[maxn],f2[maxn],x,inv[maxn]; bool vis[maxn]; void get_table() { fac[1]=1;for (int i=2;i<=maxn;i++) fac[i]=(long long)fac[i-1]*i%mod; inv[1]=1; for (int i=2;i<=maxn;i++) { inv[i]=(-(long long)mod/i*inv[mod%i]%mod+mod)%mod; if (!vis[i]) prime[++top]=i; for (int j=1;j<=top && i*prime[j]<=maxn;j++) { vis[i*prime[j]]=true; if (!(i%prime[j])) break; } } f1[0]=f2[0]=1; for (int i=1;i<=top;i++) { f1[i]=((long long)f1[i-1]*(prime[i]-1))%mod; f2[i]=((long long)f2[i-1]*inv[prime[i]])%mod; } } int find(int x) { int l=1,r=top,ans=0; while (l<=r) { int mid=l+r>>1; if (prime[mid]<=x) {ans=mid;l=mid+1;} else r=mid-1; } return ans; } int main() { scanf("%d%d",&t,&mod); get_table(); for (int i=1;i<=t;i++) { scanf("%d%d",&n,&m); x=find(m); long long ans=(((long long)fac[n]*(long long)f1[x])%mod*(long long)f2[x])%mod; printf("%lld\n",ans); } return 0; }