题目
∑ i = 1 n ∑ j = 1 m σ 1 ( g c d ( i , j ) ) [ σ 1 ( g c d ( i , j ) ) ≤ A ] \sum_{i=1}^n\sum_{j=1}^m\sigma_1(gcd(i,j))[\sigma_1(gcd(i,j))\leq A] i=1∑nj=1∑mσ1(gcd(i,j))[σ1(gcd(i,j))≤A]
题解
先不考虑A
∑
i
=
1
n
∑
j
=
1
m
σ
1
(
g
c
d
(
i
,
j
)
)
∑
d
=
1
u
p
σ
1
(
d
)
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
m
d
⌋
[
g
c
d
(
i
,
j
)
=
=
1
]
∑
d
=
1
u
p
σ
1
(
d
)
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
m
d
⌋
∑
e
∣
g
c
d
(
i
,
j
)
μ
(
e
)
∑
d
=
1
u
p
σ
1
(
d
)
∑
e
=
1
⌊
u
p
d
⌋
μ
(
e
)
⌊
n
d
e
⌋
⌊
m
d
e
⌋
∑
T
=
1
u
p
⌊
n
T
⌋
⌊
m
T
⌋
∑
d
∣
T
σ
1
(
d
)
μ
(
T
d
)
\sum_{i=1}^n\sum_{j=1}^m\sigma_1(gcd(i,j))\\ \sum_{d=1}^{up}\sigma_1(d)\sum_{i=1}^{\lfloor\frac n d\rfloor} \sum_{j=1}^{\lfloor\frac m d\rfloor}[gcd(i,j)==1]\\ \sum_{d=1}^{up}\sigma_1(d)\sum_{i=1}^{\lfloor\frac n d\rfloor} \sum_{j=1}^{\lfloor\frac m d\rfloor}\sum_{e|gcd(i,j)}\mu(e)\\ \sum_{d=1}^{up}\sigma_1(d)\sum_{e=1}^{\lfloor\frac {up} d\rfloor}\mu(e) {\lfloor\frac n {de}\rfloor}{\lfloor\frac m {de}\rfloor}\\\sum_{T=1}^{up}{\lfloor\frac n {T}\rfloor}{\lfloor\frac m {T}\rfloor}\sum_{d|T}\sigma_1(d)\mu(\frac T d)\\
i=1∑nj=1∑mσ1(gcd(i,j))d=1∑upσ1(d)i=1∑⌊dn⌋j=1∑⌊dm⌋[gcd(i,j)==1]d=1∑upσ1(d)i=1∑⌊dn⌋j=1∑⌊dm⌋e∣gcd(i,j)∑μ(e)d=1∑upσ1(d)e=1∑⌊dup⌋μ(e)⌊den⌋⌊dem⌋T=1∑up⌊Tn⌋⌊Tm⌋d∣T∑σ1(d)μ(dT)
f
(
T
)
=
∑
d
∣
T
σ
1
(
d
)
μ
(
T
d
)
f(T)=\sum_{d|T}\sigma_1(d)\mu(\frac T d)
f(T)=∑d∣Tσ1(d)μ(dT)
最后考虑把A离线下来增量累加贡献,仅当
σ
1
(
d
)
≤
A
\sigma_1(d)\leq A
σ1(d)≤A有贡献
将
σ
1
\sigma_1
σ1按大小排序,每次累加可以产生贡献的
f
(
d
)
,
f
(
2
d
)
.
.
.
f
(
x
d
)
f(d),f(2d)...f(xd)
f(d),f(2d)...f(xd)
需要用树状数组求前缀和以及单点修改
累加复杂度是
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn),询问
O
(
l
o
g
n
)
O(logn)
O(logn)
最后整除分块解决大柿子
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10,M=1e5;
const ll mod=1ll<<31;
struct qwq{
int id;ll num;
friend bool operator<(const qwq a,const qwq b){return a.num<b.num;}
}d[N];
int miu[N];
int z[N],p;
bool vis[N];
void Sieve()
{
miu[1]=1;
for(int i=2;i<=M;i++)
{
d[i].id=i;
if(!vis[i])z[++p]=i,miu[i]=-1;
for(int j=1;j<=p&&i*z[j]<=M;j++)
{
vis[i*z[j]]=1;
if(i%z[j]==0)break;
miu[i*z[j]]=-miu[i];
}
}
for(int i=1;i<=M;i++)d[i].id=i;
for(int i=1;i<=M;i++)
for(int j=i;j<=M;j+=i)d[j].num+=i;
sort(d+1,d+M+1);
}
ll t[N],key;
int lowbit(int x){return x&(-x);}
void add(int i){for(;i<=M;i+=lowbit(i))t[i]=(t[i]+key)%mod;}
ll qur(int i){ll ans=0;for(;i;i-=lowbit(i))ans=(ans+t[i])%mod;return ans;}
struct qus{
int n,m,id;ll a;
friend bool operator<(const qus x,const qus y){return x.a<y.a;}
}qs[N];
ll work(int n,int m)
{
ll ans=0;int up=min(n,m);
for(int l=1,r;l<=up;l=r+1)
{
r=min(n/(n/l),m/(m/l));
ans=(ans+(n/l)*(m/l)%mod*(qur(r)-qur(l-1)+mod)%mod)%mod;
}return ans;
}
ll ans[N];
int main()
{
int T;Sieve();
scanf("%d",&T);
for(int i=1;i<=T;i++)
scanf("%d%d%lld",&qs[i].n,&qs[i].m,&qs[i].a),qs[i].id=i;
sort(qs+1,qs+T+1);
ll pre=0;int pos=1;
for(int i=1;i<=T;i++)
{
if(pre<qs[i].a)
{
pre=qs[i].a;
while(d[pos].num<=pre&&pos<=M)
{
int x=d[pos].id;
for(int j=x;j<=M;j+=x)
{
key=(d[pos].num*miu[j/x]%mod+mod)%mod;
add(j);
}
pos++;
}
}
ans[qs[i].id]=work(qs[i].n,qs[i].m);
}
for(int i=1;i<=T;i++)printf("%lld\n",ans[i]);
}