前言
这里需要对莫反有一些基础。
不会的可以点这里
洛谷P3455
题意:
给定
a
,
b
,
d
a,b,d
a,b,d
求
∑
x
=
1
a
∑
y
=
1
b
[
gcd
(
x
,
y
)
=
d
]
\sum_{x=1}^a\sum_{y=1}^b[\gcd(x,y)=d]
∑x=1a∑y=1b[gcd(x,y)=d]
1
≤
n
≤
5
×
1
0
4
1\leq n\leq5\times 10^4
1≤n≤5×104,
1
≤
d
≤
a
,
b
≤
5
×
1
0
4
1 \leq d \leq a,b \leq 5 \times 10^4
1≤d≤a,b≤5×104
按照套路:
∑
x
=
1
a
∑
y
=
1
b
[
gcd
(
x
,
y
)
=
d
]
\sum_{x=1}^a\sum_{y=1}^b[\gcd(x,y)=d]
∑x=1a∑y=1b[gcd(x,y)=d]
=
∑
x
=
1
a
d
∑
y
=
1
b
d
[
gcd
(
x
,
y
)
=
1
]
=\sum_{x=1}^{\frac{a}{d}}\sum_{y=1}^{\frac{b}{d}}[\gcd(x,y)=1]
=∑x=1da∑y=1db[gcd(x,y)=1]
=
∑
x
=
1
a
d
∑
y
=
1
b
d
∑
k
∣
gcd
(
x
,
y
)
μ
(
k
)
=\sum_{x=1}^{\frac{a}{d}}\sum_{y=1}^{\frac{b}{d}}\sum_{k|\gcd(x,y)}\mu(k)
=∑x=1da∑y=1db∑k∣gcd(x,y)μ(k)
=
∑
x
=
1
a
d
∑
y
=
1
b
d
∑
k
=
1
μ
(
k
)
[
k
∣
gcd
(
x
,
y
)
]
=\sum_{x=1}^{\frac{a}{d}}\sum_{y=1}^{\frac{b}{d}}\sum_{k=1}\mu(k)[k|\gcd(x,y)]
=∑x=1da∑y=1db∑k=1μ(k)[k∣gcd(x,y)]
=
∑
k
=
1
min
(
a
d
,
b
d
)
μ
(
k
)
∑
x
=
1
a
d
∑
y
=
1
b
d
[
k
∣
gcd
(
x
,
y
)
]
=\sum_{k=1}^{\min(\frac{a}{d},\frac{b}{d})}\mu(k)\sum_{x=1}^{\frac{a}{d}}\sum_{y=1}^{\frac{b}{d}}[k|\gcd(x,y)]
=∑k=1min(da,db)μ(k)∑x=1da∑y=1db[k∣gcd(x,y)]
=
∑
k
=
1
min
(
a
d
,
b
d
)
μ
(
k
)
⌊
a
d
k
⌋
⌊
b
d
k
⌋
=\sum_{k=1}^{\min(\frac{a}{d},\frac{b}{d})}\mu(k)\left\lfloor\frac{\frac{a}{d}}{k}\right\rfloor\left\lfloor\frac{\frac{b}{d}}{k}\right\rfloor
=∑k=1min(da,db)μ(k)⌊kda⌋⌊kdb⌋
数论分块解决即可。
Code:
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
using namespace std;
const int N=2e6+1,M=2e6+1;
int t,n,m,k,ans=0;
struct fy{
int prv[N],cnt,mu[N],sum[N];
bool pr[N];
void ola(int x){
pr[1]=mu[1]=1;
for(int i=2;i<=x;i++){
if(!pr[i])
prv[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&i*prv[j]<=x;j++){
int u=i*prv[j];
pr[u]=1;
if(i%prv[j]==0){
mu[u]=0;
break;
}
else{
mu[u]=-mu[i];
}
}
}
for(int i=1;i<=x;i++)
sum[i]=sum[i-1]+mu[i];
}
}A;
signed main(){
IOS;
A.ola(N-1);
cin>>t;
while(t--){
cin>>n>>m>>k;
n/=k,m/=k;
ans=0;
for(int l=1,r;l<=min(n,m);l=r+1){
r=min(n/(n/l),m/(m/l));
ans+=(A.sum[r]-A.sum[l-1])*(n/l)*(m/l);
}
cout<<ans<<"\n";
}
return 0;
}
洛谷P1829
题意:给定
n
,
m
n,m
n,m,求
∑
i
=
1
n
∑
j
=
1
m
l
c
m
(
i
,
j
)
\sum_{i=1}^n\sum_{j=1}^m lcm(i,j)
∑i=1n∑j=1mlcm(i,j)
1
≤
n
,
m
≤
1
0
7
1\leq n,m\leq 10^7
1≤n,m≤107
∑
i
=
1
n
∑
j
=
1
m
l
c
m
(
i
,
j
)
\sum_{i=1}^n\sum_{j=1}^m lcm(i,j)
∑i=1n∑j=1mlcm(i,j)
=
∑
i
=
1
n
∑
j
=
1
m
i
j
gcd
(
i
,
j
)
=\sum_{i=1}^n\sum_{j=1}^m\frac{ij}{\gcd(i,j)}
=∑i=1n∑j=1mgcd(i,j)ij
令
o
=
min
(
n
,
m
)
o=\min(n,m)
o=min(n,m)
=
∑
d
=
1
o
∑
i
=
1
n
∑
j
=
1
m
[
gcd
(
i
,
j
)
=
d
]
i
j
d
=\sum_{d=1}^o\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=d]\frac{ij}{d}
=∑d=1o∑i=1n∑j=1m[gcd(i,j)=d]dij
令
a
=
⌊
n
d
⌋
,
b
=
⌊
m
d
⌋
,
c
=
min
(
a
,
b
)
a=\left\lfloor\frac{n}{d}\right\rfloor,b=\left\lfloor\frac{m}{d}\right\rfloor,c=\min(a,b)
a=⌊dn⌋,b=⌊dm⌋,c=min(a,b)
=
∑
d
=
1
o
d
∑
i
=
1
a
∑
j
=
1
b
[
gcd
(
i
,
j
)
=
1
]
i
j
=\sum_{d=1}^o d\sum_{i=1}^a\sum_{j=1}^b[\gcd(i,j)=1]ij
=∑d=1od∑i=1a∑j=1b[gcd(i,j)=1]ij
=
∑
d
=
1
o
d
∑
i
=
1
a
∑
j
=
1
b
i
j
∑
k
∣
gcd
(
i
,
j
)
μ
(
k
)
=\sum_{d=1}^o d\sum_{i=1}^a\sum_{j=1}^bij\sum_{k|\gcd(i,j)}\mu(k)
=∑d=1od∑i=1a∑j=1bij∑k∣gcd(i,j)μ(k)
=
∑
d
=
1
o
d
∑
k
=
1
c
μ
(
k
)
∑
i
=
1
a
∑
j
=
1
b
i
j
[
k
∣
gcd
(
i
,
j
)
]
=\sum_{d=1}^o d\sum_{k=1}^c\mu(k)\sum_{i=1}^a\sum_{j=1}^bij[k|\gcd(i,j)]
=∑d=1od∑k=1cμ(k)∑i=1a∑j=1bij[k∣gcd(i,j)]
=
∑
d
=
1
o
d
∑
k
=
1
c
μ
(
k
)
∑
i
=
1
⌊
a
k
⌋
∑
j
=
1
⌊
b
k
⌋
i
k
⋅
j
k
=\sum_{d=1}^o d\sum_{k=1}^c\mu(k)\sum_{i=1}^{\left\lfloor\frac{a}{k}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{b}{k}\right\rfloor}ik\cdot jk
=∑d=1od∑k=1cμ(k)∑i=1⌊ka⌋∑j=1⌊kb⌋ik⋅jk
=
∑
d
=
1
o
d
∑
k
=
1
c
μ
(
k
)
∑
i
=
1
⌊
a
k
⌋
∑
j
=
1
⌊
b
k
⌋
i
j
k
2
=\sum_{d=1}^o d\sum_{k=1}^c\mu(k)\sum_{i=1}^{\left\lfloor\frac{a}{k}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{b}{k}\right\rfloor}ijk^2
=∑d=1od∑k=1cμ(k)∑i=1⌊ka⌋∑j=1⌊kb⌋ijk2
=
∑
d
=
1
o
d
∑
k
=
1
c
μ
(
k
)
k
2
∑
i
=
1
⌊
a
k
⌋
i
∑
j
=
1
⌊
b
k
⌋
j
=\sum_{d=1}^o d\sum_{k=1}^c\mu(k)k^2\sum_{i=1}^{\left\lfloor\frac{a}{k}\right\rfloor}i\sum_{j=1}^{\left\lfloor\frac{b}{k}\right\rfloor}j
=∑d=1od∑k=1cμ(k)k2∑i=1⌊ka⌋i∑j=1⌊kb⌋j
令
s
u
m
(
n
)
=
∑
i
=
1
n
i
,
T
=
k
d
sum(n)=\sum_{i=1}^ni,T=kd
sum(n)=∑i=1ni,T=kd
=
∑
d
=
1
o
d
∑
k
=
1
c
μ
(
k
)
k
2
s
u
m
(
⌊
a
k
⌋
)
s
u
m
(
⌊
b
k
⌋
)
=\sum_{d=1}^o d\sum_{k=1}^c\mu(k)k^2sum(\left\lfloor\frac{a}{k}\right\rfloor)sum(\left\lfloor\frac{b}{k}\right\rfloor)
=∑d=1od∑k=1cμ(k)k2sum(⌊ka⌋)sum(⌊kb⌋)
=
∑
d
=
1
o
d
∑
k
=
1
min
(
⌊
n
d
⌋
,
⌊
m
d
⌋
)
μ
(
k
)
k
2
s
u
m
(
⌊
n
k
d
⌋
)
s
u
m
(
⌊
m
k
d
⌋
)
=\sum_{d=1}^o d\sum_{k=1}^{\min(\left\lfloor\frac{n}{d}\right\rfloor,\left\lfloor\frac{m}{d}\right\rfloor)}\mu(k)k^2sum(\left\lfloor\frac{n}{kd}\right\rfloor)sum(\left\lfloor\frac{m}{kd}\right\rfloor)
=∑d=1od∑k=1min(⌊dn⌋,⌊dm⌋)μ(k)k2sum(⌊kdn⌋)sum(⌊kdm⌋)
=
∑
T
=
1
o
s
u
m
(
n
T
)
s
u
m
(
m
T
)
T
∑
d
∣
T
d
μ
(
d
)
=\sum_{T=1}^osum(\frac{n}{T})sum(\frac{m}{T})T\sum_{d|T}d\mu(d)
=∑T=1osum(Tn)sum(Tm)T∑d∣Tdμ(d)
令
g
(
n
)
=
∑
d
∣
n
d
μ
(
d
)
g(n)=\sum_{d|n}d\mu(d)
g(n)=∑d∣ndμ(d)
=
∑
T
=
1
o
s
u
m
(
n
T
)
s
u
m
(
m
T
)
T
g
(
T
)
=\sum_{T=1}^osum(\frac{n}{T})sum(\frac{m}{T})Tg(T)
=∑T=1osum(Tn)sum(Tm)Tg(T)
考虑线性筛出
g
(
n
)
g(n)
g(n)
还可以用数论分块优化,但也可以不用。
Code:
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
using namespace std;
const int N=1e7+1,mod=20101009;
int t,n,m,k;
struct fy{
int prv[N],cnt,g[N],s[N];
bool pr[N];
void ola(int x){
pr[1]=g[1]=1;
for(int i=2;i<=x;i++){
if(!pr[i])
prv[++cnt]=i,g[i]=(1-i+mod)%mod;
for(int j=1;j<=cnt&&i*prv[j]<=x;j++){
int u=i*prv[j];
pr[u]=1;
if(i%prv[j]==0){
g[u]=g[i];
break;
}
else{
g[u]=g[i]*g[prv[j]]%mod;
}
}
}
}
void getsum(int x){
for(int i=1;i<=x;i++)
s[i]=(s[i-1]+i)%mod;
}
}A;
signed main(){
IOS;
A.ola(N-1);
A.getsum(N-1);
cin>>n>>m;
int ans=0;
for(int i=1;i<=min(n,m);i++){
ans+=A.s[n/i]*A.s[m/i]%mod*i%mod*A.g[i]%mod;
ans%=mod;
}
cout<<ans;
return 0;
}
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
using namespace std;
const int N=1e7+1,mod=20101009;
int t,n,m,k;
struct fy{
int prv[N],cnt,g[N],s[N];
bool pr[N];
void ola(int x){
pr[1]=g[1]=1;
for(int i=2;i<=x;i++){
if(!pr[i])
prv[++cnt]=i,g[i]=(1-i+mod)%mod;
for(int j=1;j<=cnt&&i*prv[j]<=x;j++){
int u=i*prv[j];
pr[u]=1;
if(i%prv[j]==0){
g[u]=g[i];
break;
}
else{
g[u]=g[i]*g[prv[j]]%mod;
}
}
}
}
void getsum(int x){
for(int i=1;i<=x;i++)
s[i]=(s[i-1]+i)%mod,g[i]=(i*g[i]+g[i-1])%mod;
}
}A;
signed main(){
IOS;
A.ola(N-1);
A.getsum(N-1);
cin>>n>>m;
int ans=0;
for(int l=1,r;l<=min(n,m);l=r+1){
r=min(n/(n/l),m/(m/l));
ans+=A.s[n/l]*A.s[m/l]%mod*((A.g[r]-A.g[l-1]+mod)%mod)%mod;
ans%=mod;
}
cout<<ans;
return 0;
}
洛谷P4449
题意:给定
n
,
m
,
k
n,m,k
n,m,k,求
∑
i
=
1
n
∑
j
=
1
m
gcd
(
i
,
j
)
k
\sum_{i=1}^n\sum_{j=1}^m\gcd(i,j)^k
∑i=1n∑j=1mgcd(i,j)k
1
≤
T
≤
2
×
1
0
3
,
1
≤
n
,
m
,
k
≤
5
×
1
0
6
1 \leq T \leq 2 \times 10^3,1\leq n, m, k \leq 5\times10^6
1≤T≤2×103,1≤n,m,k≤5×106
∑
i
=
1
n
∑
j
=
1
m
gcd
(
i
,
j
)
k
\sum_{i=1}^n\sum_{j=1}^m\gcd(i,j)^k
∑i=1n∑j=1mgcd(i,j)k
a
,
b
,
c
,
o
a,b,c,o
a,b,c,o的含义同上文。
=
∑
d
=
1
o
d
k
∑
i
=
1
n
∑
j
=
1
m
[
gcd
(
i
,
j
)
=
d
]
=\sum_{d=1}^od^k\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=d]
=∑d=1odk∑i=1n∑j=1m[gcd(i,j)=d]
=
∑
d
=
1
o
d
k
∑
p
=
1
c
μ
(
p
)
⌊
a
p
⌋
⌊
b
p
⌋
=\sum_{d=1}^od^k\sum_{p=1}^c\mu(p)\left\lfloor\frac{a}{p}\right\rfloor\left\lfloor\frac{b}{p}\right\rfloor
=∑d=1odk∑p=1cμ(p)⌊pa⌋⌊pb⌋
令
T
=
d
p
T=dp
T=dp
=
∑
d
=
1
o
d
k
∑
p
=
1
c
μ
(
p
)
⌊
n
T
⌋
⌊
n
T
⌋
=\sum_{d=1}^od^k\sum_{p=1}^c\mu(p)\left\lfloor\frac{n}{T}\right\rfloor\left\lfloor\frac{n}{T}\right\rfloor
=∑d=1odk∑p=1cμ(p)⌊Tn⌋⌊Tn⌋
=
∑
T
=
1
o
⌊
n
T
⌋
⌊
n
T
⌋
∑
d
∣
T
d
k
μ
(
T
d
)
=\sum_{T=1}^o\left\lfloor\frac{n}{T}\right\rfloor\left\lfloor\frac{n}{T}\right\rfloor\sum_{d|T}d^k\mu(\frac{T}{d})
=∑T=1o⌊Tn⌋⌊Tn⌋∑d∣Tdkμ(dT)
就跟上一题一样了,线性筛+数论分块。
Code:
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
using namespace std;
const int N=5e6+1,mod=1e9+7;
int t,n,m,k;
struct fy{
int prv[N],cnt,g[N],s[N];
bool pr[N];
inline int qmi(int x,int y){
int res=1;
while(y>0){
if(y&1)
res=res*x%mod;
x=x*x%mod,y>>=1;
}
return res;
}
void ola(int x){
pr[1]=g[1]=1;
for(int i=2;i<=x;i++){
if(!pr[i])
prv[++cnt]=i,g[i]=(qmi(i,k)-1+mod)%mod;
for(int j=1;j<=cnt&&i*prv[j]<=x;j++){
int u=i*prv[j];
pr[u]=1;
if(i%prv[j]==0){
g[u]=g[i]*qmi(prv[j],k)%mod;
break;
}
else{
g[u]=g[i]*g[prv[j]]%mod;
}
}
}
}
void getsum(int x){
for(int i=1;i<=x;i++)
g[i]=(g[i]+g[i-1])%mod;
}
}A;
signed main(){
IOS;
cin>>t>>k;
A.ola(N-1);
A.getsum(N-1);
while(t--){
cin>>n>>m;
int ans=0;
for(int l=1,r;l<=min(n,m);l=r+1){
r=min(n/(n/l),m/(m/l));
ans+=(n/l)*(m/l)%mod*((A.g[r]-A.g[l-1]+mod)%mod)%mod;
ans%=mod;
}
cout<<ans<<"\n";
}
return 0;
}