大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:
现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞票。
房地产第一大户沙拉公主决定预测一下大富翁国现在所有真钞票的数量。
现在,请你帮助沙拉公主解决这个问题,由于可能张数非常大,你只需计算出对R取模后的答案即可。
R是一个质数。
大富翁国因为通货膨胀,以及假钞泛滥,政府决定推出一项新的政策:
现有钞票编号范围为1到N的阶乘,但是,政府只发行编号与M!互质的钞票。
房地产第一大户沙拉公主决定预测一下大富翁国现在所有真钞票的数量。
现在,请你帮助沙拉公主解决这个问题,由于可能张数非常大,你只需计算出对R取模后的答案即可。
R是一个质数。
第一行为两个整数T,R。R<=10^9+10,T<=10000,表示该组中测试数据数目,R为模后面T行,每行一对整数N,M,见题目描述 m<=n
共T行,对于每一对N,M,输出1至N!中与M!素质的数的数量对R取模后的值
#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 10000010
#define MAXM 664580
using namespace std;
int p;
int fact[MAXN],inv[MAXN],phi[MAXN];
int k=0,prime[MAXM];
bool np[MAXN];
inline int read(){
int date=0,w=1;char c=0;
while(c<‘0‘||c>‘9‘){if(c==‘-‘)w=-1;c=getchar();}
while(c>=‘0‘&&c<=‘9‘){date=date*10+c-‘0‘;c=getchar();}
return date*w;
}
void make(){
int m=MAXN-10;
phi[1]=fact[1]=inv[1]=1;
for(int i=2;i<=m;i++){
fact[i]=(long long)1LL*fact[i-1]*i%p;
if(i<p)inv[i]=(long long)1LL*(p-p/i)*inv[p%i]%p;
if(!np[i])prime[++k]=i;
for(int j=1;j<=k&&prime[j]*i<=m;j++){
np[prime[j]*i]=true;
if(i%prime[j]==0)break;
}
}
for(int i=2;i<=m;i++){
if(!np[i])phi[i]=(long long)1LL*phi[i-1]*(i-1)%p*inv[i%p]%p;
else phi[i]=phi[i-1];
}
}
inline long long solve(long long n,long long m){
if(m<p&&p<=n)return 0;
return (long long)(1LL*fact[n]*phi[m]%p);
}
int main(){
int t=read();p=read();
make();
while(t--){
int n=read(),m=read();
printf("%lld\n",solve(n,m));
}
return 0;
}
原文:https://www.cnblogs.com/Yangrui-Blog/p/9484373.html