小于等于
m!
中与
m!
互质的数的个数就是
phi(m!)
,求
n!
以内且
n>=m
中与
m!
互质的个数就是
phi(m!)∗n!m!
,因为若
x
与
phi(m!)=m!∏p[i]−1p[i]
p[i]
为质因数。
那么答案就是
∏p[i]−1p[i]∗n!
分别预处理一下就行了。求逆元可以用费马小定理或者扩展欧几里得。
也不知道是不是自己写丑了。。扩欧比快速幂快了3s。。
费马小定理,用快速幂求逆元。(卡着时限过。。)
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#define N 10000005
#define INF 0x7fffffff
using namespace std;
typedef long long ll;
typedef pair<int,int> pa;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int T,mod,n,m;
int p[664580],Not_Prime[N]={1,1},sum[N],Jc[N];
int f[N];
void Get_Prime()
{
for(int i=2;i<N;i++)
{
if(!Not_Prime[i]) p[++p[0]]=i;
for(int j=1;j<=p[0]&&(ll)i*p[j]<N;j++)
{
Not_Prime[i*p[j]]=1;
if(!(i%p[j])) break;
}
}
}
int Qpow(int x,int y)
{
int rtn=1;
while(y) {
if(y&1) rtn=((ll)rtn*x)%mod;
x=((ll)x*x)%mod;y>>=1;
}
return rtn;
}
int main()
{
T=read(),mod=read();
Get_Prime();f[1]=Jc[1]=1;
for(int i=2;i<N;i++) Jc[i]=((ll)Jc[i-1]*i)%mod;
for(int i=2;i<N;i++)
{
f[i]=f[i-1];
if(!Not_Prime[i]) f[i]=(ll)f[i]*Qpow(i,mod-2)%mod*(ll)(i-1)%mod;
}
while(T--)
{
n=read(),m=read();
printf("%d\n",(ll)Jc[n]*f[m]%mod);
}
return 0;
}
扩欧求逆元
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#define N 10000005
#define INF 0x7fffffff
using namespace std;
typedef long long ll;
typedef pair<int,int> pa;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int T,mod,n,m;
int p[664580],Not_Prime[N]={1,1},sum[N],Jc[N];
int f[N];
void Get_Prime()
{
for(int i=2;i<N;i++)
{
if(!Not_Prime[i]) p[++p[0]]=i;
for(int j=1;j<=p[0]&&(ll)i*p[j]<N;j++)
{
Not_Prime[i*p[j]]=1;
if(!(i%p[j])) break;
}
}
}
int exgcd(int a,int b,int &x,int &y)
{
int rtn=a;
if(b) {
rtn=exgcd(b,a%b,y,x);
y-=(a/b)*x;
}
else x=1,y=0;
return rtn;
}
int main()
{
T=read(),mod=read();
Get_Prime();f[1]=Jc[1]=1;
for(int i=2;i<N;i++) Jc[i]=((ll)Jc[i-1]*i)%mod;
for(int i=2;i<N;i++)
{
f[i]=f[i-1];
if(!Not_Prime[i])
{
int x,y;
exgcd(i,mod,x,y);x%=mod;while(x<0) x+=mod;
f[i]=(ll)f[i]*x%mod*(ll)(i-1)%mod;
}
}
while(T--)
{
n=read(),m=read();
printf("%d\n",(ll)Jc[n]*f[m]%mod);
}
return 0;
}