题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2186
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<math.h>
#include<ctype.h>
#include<time.h>
#include<stack>
#include<queue>
#include<bitset>
#include<set>
#include<map>
#include<vector>
#include<sstream>
using namespace std;
typedef long long ll;
void fre(){freopen("in.txt","r",stdin);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define zero(a) fabs(a)<eps
#define equal(a,b) zero(a-b)
const int pi=acos(-1);
double e=2.718281828;
const int N=1000000;
int t,mod,n,m,cnt;
int fac[N+5],ine[N+5],x[500005],ans[N+5];
bool flag[N+5];
void exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
return;
}
exgcd(b,a%b,x,y);
int t=x;x=y;y=t-a/b*y;
}
int getine(int t)
{
int x,y;
exgcd(t,mod,x,y);
return (x%mod+mod)%mod;
}
void init()
{
fac[1]=1;
for(int i=2;i<=N;i++)
fac[i]=(ll)fac[i-1]*i%mod;
ine[1]=1;
for(int i=2;i<=N;i++)
{
if(!flag[i])
x[++cnt]=i,ine[i]=getine(i);
for(int j=1;x[j]*i<=N&&j<=cnt;j++)
{
flag[x[j]*i]=1;
//ine[pri[j]*i]=(ll)ine[pri[j]]*ine[i]%R;
if(i%x[j]==0)break;
}
}
ans[1]=1;
for(int i=2;i<=N;i++)
{
ans[i]=ans[i-1];
if(!flag[i])
ans[i]=(ll)ans[i]*(i-1)%mod*ine[i]%mod;
}
}
int main()
{
scanf("%d%d",&t,&mod);
init();
while(t--)
{
scanf("%d%d",&n,&m);
printf("%I64d\n",(ll)fac[n]*ans[m]%mod);
}
return 0;
}
分析:题目要求[1,n!]里与m!互质的数的个数,[1,m!]中与m!互质的数有 Oular(m!) 个,对于每个互质的
数,如果我们给他都加上M!,仍然和m!互质,即求 Oular(m!)∗n!/m! , 根据欧拉函数的性质,可以把
Oular(m!) 化简为 m!∗∏((p−1)/p) ,p为m!的质因数,就变成了求 n!∗∏((p−1)/p) ,求到此就很清晰了,
预处理线性筛出[1,10000000]的素数,求出逆元,同时求出阶乘取模,随便搞搞就出来了。