题目
求 ∑ i = 1 n ! [ g c d ( i , m ! ) = = 1 ] \sum_{i=1}^{n!}[gcd(i,m!)==1] i=1∑n![gcd(i,m!)==1]
分析
显然可知答案求的是
n
!
m
!
φ
(
m
!
)
=
n
!
∏
i
=
1
k
p
k
−
1
p
k
\frac{n!}{m!}\varphi(m!)=n!\prod_{i=1}^k\frac{p_k-1}{p_k}
m!n!φ(m!)=n!i=1∏kpkpk−1
要注意有一些特殊例子,不要以为只要
n
≥
m
o
d
n\geq mod
n≥mod答案一定是0,可以约分掉,所以要在阶乘和逆元都同时消掉
代码
#include <cstdio>
#include <cctype>
#define rr register
const int N=10000001; bool v[N];
int T,mod,inv[N],pac[N],pnv[N],fac[N],cnt,prime[N],dep[N];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
signed main(){
T=iut(); mod=iut();
v[0]=v[1]=inv[0]=inv[1]=pac[0]=pnv[0]=fac[0]=1;
for (rr int i=2;i<N;++i){
if (!v[i]) prime[++cnt]=i;
for (rr int j=1;prime[j]*i<N&&j<=cnt;++j){
v[i*prime[j]]=1;
if (i%prime[j]==0) break;
}
}
rr int t=mod<N?mod:N;
for (rr int i=2;i<t;++i) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
for (rr int i=1;i<=cnt;++i) pac[i]=1ll*pac[i-1]*(prime[i]-1)%mod;
for (rr int i=1;i<=cnt;++i) pnv[i]=1ll*pnv[i-1]*inv[prime[i]%mod]%mod;
for (rr int i=1;i<N;++i) if (i!=mod) fac[i]=1ll*fac[i-1]*i%mod; else fac[i]=fac[i-1];
for (rr int i=2;i<N;++i) dep[i]=dep[i-1]+(!v[i]);
while (T--){
rr int n=iut(),m=iut();
if (n>=mod&&m<mod) putchar(48),putchar(10);
else print(1ll*fac[n]*pac[dep[m]]%mod*pnv[dep[m]]%mod),putchar(10);
}
return 0;
}