题目:hdu6390.
题目大意:给定
n
,
m
,
p
n,m,p
n,m,p,
p
p
p为素数,求:
∑
i
=
1
n
∑
j
=
1
m
ϕ
(
i
j
)
ϕ
(
i
)
ϕ
(
j
)
  
(
m
o
d
  
p
)
\sum_{i=1}^{n}\sum_{j=1}^{m}\frac{\phi(ij)}{\phi(i)\phi(j)}\,\,(mod\,\,p)
i=1∑nj=1∑mϕ(i)ϕ(j)ϕ(ij)(modp)
1 ≤ n , m ≤ m i n ( 1 0 6 , p ) , 1 ≤ p ≤ 1 0 9 + 7 1\leq n,m\leq min(10^6,p),1\leq p\leq 10^9+7 1≤n,m≤min(106,p),1≤p≤109+7,最多三组数据.
先考虑如何化简 ϕ ( i j ) ϕ ( i ) ϕ ( j ) \frac{\phi(ij)}{\phi(i)\phi(j)} ϕ(i)ϕ(j)ϕ(ij),显然除了 i , j i,j i,j的共有质因子外其它因子都会被约分掉,所以我们先取出共有的部分 g = g c d ( i , j ) g=gcd(i,j) g=gcd(i,j).
考虑把共有部分唯一分解
g
=
∏
l
=
1
k
p
l
c
l
g=\prod_{l=1}^{k}p_l^{c_l}
g=∏l=1kplcl,显然最后的答案就会变成:
ϕ
(
i
j
)
ϕ
(
i
)
ϕ
(
j
)
=
g
g
∏
l
=
1
k
p
l
−
1
p
l
=
g
c
d
(
i
,
j
)
ϕ
(
g
c
d
(
i
,
j
)
)
\frac{\phi(ij)}{\phi(i)\phi(j)}=\frac{g}{g\prod_{l=1}^{k}\frac{p_l-1}{p_l}}=\frac{gcd(i,j)}{\phi(gcd(i,j))}
ϕ(i)ϕ(j)ϕ(ij)=g∏l=1kplpl−1g=ϕ(gcd(i,j))gcd(i,j)
这个式子看起来比原来优美多了,所以开始推导:
∑
i
=
1
n
∑
j
=
1
m
ϕ
(
i
j
)
ϕ
(
i
)
ϕ
(
j
)
=
∑
i
=
1
n
∑
j
=
1
m
g
c
d
(
i
,
j
)
ϕ
(
g
c
d
(
i
,
j
)
)
=
∑
d
=
1
m
i
n
(
n
,
m
)
d
ϕ
(
d
)
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
m
d
⌋
[
g
c
d
(
i
,
j
)
=
1
]
=
∑
d
=
1
m
i
n
(
n
,
m
)
d
ϕ
(
d
)
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
m
d
⌋
∑
t
∣
i
∪
t
∣
j
μ
(
t
)
=
∑
d
=
1
m
i
n
(
n
,
m
)
d
ϕ
(
d
)
∑
t
=
1
⌊
m
i
n
(
n
,
m
)
d
⌋
μ
(
t
)
⌊
n
d
t
⌋
⌊
m
d
t
⌋
=
∑
c
=
1
m
i
n
(
n
,
m
)
⌊
n
c
⌋
⌊
m
c
⌋
∑
d
∣
c
d
ϕ
(
d
)
μ
(
c
d
)
\sum_{i=1}^{n}\sum_{j=1}^{m}\frac{\phi(ij)}{\phi(i)\phi(j)}\\ =\sum_{i=1}^{n}\sum_{j=1}^{m}\frac{gcd(i,j)}{\phi(gcd(i,j))}\\ =\sum_{d=1}^{min(n,m)}\frac{d}{\phi(d)}\sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{m}{d}\right\rfloor}[gcd(i,j)=1]\\ =\sum_{d=1}^{min(n,m)}\frac{d}{\phi(d)}\sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{m}{d}\right\rfloor}\sum_{t|i\cup t|j}\mu(t)\\ =\sum_{d=1}^{min(n,m)}\frac{d}{\phi(d)}\sum_{t=1}^{\left\lfloor\frac{min(n,m)}{d}\right\rfloor}\mu(t)\left\lfloor\frac{n}{dt}\right\rfloor\left\lfloor\frac{m}{dt}\right\rfloor\\ =\sum_{c=1}^{min(n,m)}\left\lfloor\frac{n}{c}\right\rfloor\left\lfloor\frac{m}{c}\right\rfloor\sum_{d|c}\frac{d}{\phi(d)}\mu(\frac{c}{d})
i=1∑nj=1∑mϕ(i)ϕ(j)ϕ(ij)=i=1∑nj=1∑mϕ(gcd(i,j))gcd(i,j)=d=1∑min(n,m)ϕ(d)di=1∑⌊dn⌋j=1∑⌊dm⌋[gcd(i,j)=1]=d=1∑min(n,m)ϕ(d)di=1∑⌊dn⌋j=1∑⌊dm⌋t∣i∪t∣j∑μ(t)=d=1∑min(n,m)ϕ(d)dt=1∑⌊dmin(n,m)⌋μ(t)⌊dtn⌋⌊dtm⌋=c=1∑min(n,m)⌊cn⌋⌊cm⌋d∣c∑ϕ(d)dμ(dc)
我们设
f
(
n
)
=
∑
d
∣
n
d
ϕ
(
d
)
μ
(
n
d
)
f(n)=\sum_{d|n}\frac{d}{\phi(d)}\mu(\frac{n}{d})
f(n)=∑d∣nϕ(d)dμ(dn),发现这是个积性函数,可以线性筛:
1.
i
=
1
i=1
i=1,则
f
(
i
)
=
1
f(i)=1
f(i)=1.
2.
i
i
i为素数,则
f
(
i
)
=
1
ϕ
(
1
)
μ
(
i
)
+
i
ϕ
(
i
)
μ
(
1
)
=
1
i
−
1
f(i)=\frac{1}{\phi(1)}\mu(i)+\frac{i}{\phi(i)}\mu(1)=\frac{1}{i-1}
f(i)=ϕ(1)1μ(i)+ϕ(i)iμ(1)=i−11.
3.
g
c
d
(
i
,
p
)
=
1
gcd(i,p)=1
gcd(i,p)=1,则
f
(
i
p
)
=
f
(
i
)
f
(
p
)
f(ip)=f(i)f(p)
f(ip)=f(i)f(p).
4.当
p
p
p为素数且
p
∣
i
p|i
p∣i时,先考虑
i
=
p
c
i=p^c
i=pc的情况:
f
(
i
p
)
=
f
(
p
c
+
1
)
=
∑
d
∣
p
c
+
1
d
ϕ
(
d
)
μ
(
p
c
+
1
d
)
=
−
p
c
ϕ
(
p
c
)
+
p
c
+
1
ϕ
(
p
c
+
1
)
=
−
p
c
(
p
−
1
)
p
c
−
1
+
p
c
+
1
(
p
−
1
)
p
c
=
0
f(ip)=f(p^{c+1})=\sum_{d|p^{c+1}}\frac{d}{\phi(d)}\mu(\frac{p^{c+1}}{d})\\ =-\frac{p^c}{\phi(p^c)}+\frac{p^{c+1}}{\phi(p^{c+1})}\\ =-\frac{p^c}{(p-1)p^{c-1}}+\frac{p^{c+1}}{(p-1)p^c}\\ =0
f(ip)=f(pc+1)=d∣pc+1∑ϕ(d)dμ(dpc+1)=−ϕ(pc)pc+ϕ(pc+1)pc+1=−(p−1)pc−1pc+(p−1)pcpc+1=0
然后我们用除法分块处理一下,就可以做到 O ( T n ) O(Tn) O(Tn)解决这个问题了.
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=1000000;
int n,m;
LL inv[N+9],mod;
void pre_inv(int n,LL mod){
inv[1]=1;
for (int i=2;i<=n;++i)
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}
int tp,pr[N+9],b[N+9];
LL f[N+9];
void sieve(int n){
f[1]=1;tp=0;
for (int i=2;i<=n;++i) b[i]=1;
for (int i=2;i<=n;++i){
if (b[i]) pr[++tp]=i,f[i]=inv[i-1];
for (int j=1;j<=tp&&i*pr[j]<=n;++j){
b[i*pr[j]]=0;
if (i%pr[j]==0){f[i*pr[j]]=0;break;}
f[i*pr[j]]=f[i]*f[pr[j]]%mod;
}
}
}
LL Query(int n,int m){
LL ans=0;
for (int l=1,r;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
ans=(ans+(f[r]-f[l-1]+mod)*(n/l)%mod*(m/l))%mod;
}
return ans;
}
Abigail into(){
scanf("%d%d%lld",&n,&m,&mod);
}
Abigail work(){
if (n>m) swap(n,m);
pre_inv(n,mod);
sieve(n);
for (int i=1;i<=n;++i){
f[i]+=f[i-1];
if (f[i]>=mod) f[i]-=mod;
}
}
Abigail outo(){
printf("%lld\n",Query(n,m));
}
int main(){
int T;
scanf("%d",&T);
while (T--){
into();
work();
outo();
}
return 0;
}