正题
题目大意
给出n,m,a,求 ∑ i = 1 n ∑ j = 1 m σ ( g c d ( i , j ) ) [ σ ( g c d ( i , j ) ) ≤ a ] \sum_{i=1}^n\sum_{j=1}^m\sigma(gcd(i,j))[\sigma(gcd(i,j))\leq a] i=1∑nj=1∑mσ(gcd(i,j))[σ(gcd(i,j))≤a]
解题思路
先不考虑a的条件限制
∑
i
=
1
n
∑
j
=
1
m
σ
(
g
c
d
(
i
,
j
)
)
\sum_{i=1}^n\sum_{j=1}^m\sigma(gcd(i,j))
i=1∑nj=1∑mσ(gcd(i,j))
∑
d
=
1
n
σ
(
d
)
∑
i
=
1
n
/
d
∑
j
=
1
m
/
d
∑
c
∣
i
,
c
∣
j
μ
(
c
)
\sum_{d=1}^n\sigma(d)\sum_{i=1}^{n/d}\sum_{j=1}^{m/d}\sum_{c|i,c|j}\mu(c)
d=1∑nσ(d)i=1∑n/dj=1∑m/dc∣i,c∣j∑μ(c)
∑
d
=
1
n
σ
(
d
)
∑
c
∣
i
,
c
∣
j
μ
(
c
)
⌊
n
c
d
⌋
⌊
m
c
d
⌋
\sum_{d=1}^n\sigma(d)\sum_{c|i,c|j}\mu(c)\left\lfloor\frac{n}{cd}\right\rfloor\left\lfloor\frac{m}{cd}\right\rfloor
d=1∑nσ(d)c∣i,c∣j∑μ(c)⌊cdn⌋⌊cdm⌋
设k=cd,枚举k
∑ k = 1 n ⌊ n k ⌋ ⌊ m k ⌋ ∑ d ∣ k σ ( d ) μ ( k d ) \sum_{k=1}^n\left\lfloor\frac{n}{k}\right\rfloor\left\lfloor\frac{m}{k}\right\rfloor\sum_{d|k}\sigma(d)\mu(\frac{k}{d}) k=1∑n⌊kn⌋⌊km⌋d∣k∑σ(d)μ(dk)
对于后面一部分可以预处理出来
然后整除分块即可
考虑a的限制条件,可以离线处理
先对a进行排序,只计算满足条件的d,对于一段区间的和可以用树状数组
时间复杂度 O ( T n l o g n ) O(T\sqrt{n}\ log\ n) O(Tn log n)
code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 100100
#define mod 2147483648
#define mp make_pair
#define fs first
#define sn second
using namespace std;
ll t,w,n,m,ans,now,g[N],f[N],p[N],c[N],qs[N],mu[N],prime[N];
pair<ll,ll>a[N];
struct node
{
ll n,m,a,v;
}q[N];
bool cmp(node a,node b)
{
return a.a<b.a;
}
void work()
{
mu[1]=f[1]=1;
for(ll i=2;i<=1e5;++i){
if(!p[i]){
prime[++w]=i;
mu[i]=-1;
f[i]=i+1;
g[i]=i+1;
}
for(ll j=1;j<=w&&i*prime[j]<=1e5;++j){
p[i*prime[j]]=1;
if(i%prime[j]==0){
g[i*prime[j]]=g[i]*prime[j]+1;
f[i*prime[j]]=f[i]/g[i]*g[i*prime[j]];
}
else{
mu[i*prime[j]]=-mu[i];
g[i*prime[j]]=prime[j]+1;
f[i*prime[j]]=f[i]*g[i*prime[j]];
}
}
}
for(ll i=1;i<=1e5;++i)
a[i]=mp(f[i],i);
sort(a+1,a+1+100000);
return;
}
void add(ll x,ll y)
{
for(;x<=1e5;x+=x&-x)
(c[x]+=y)%=mod;
return;
}
ll ask(ll x)
{
ll sum=0;
for(;x;x-=x&-x)
(sum+=c[x])%=mod;
return sum;
}
int main()
{
scanf("%lld",&t);
for(ll i=1;i<=t;++i){
scanf("%lld%lld%lld",&q[i].n,&q[i].m,&q[i].a);
q[i].v=i;
}
sort(q+1,q+1+t,cmp);
work();
now=1;
for(ll i=1;i<=t;++i){
while(now<=1e5&&a[now].fs<=q[i].a){
for(ll j=1;a[now].sn*j<=1e5;++j)
add(a[now].sn*j,(a[now].fs*mu[j]%mod+mod)%mod);
now++;
}
ans=0;
n=q[i].n;
m=q[i].m;
for(ll l=1,r=0;l<=min(n,m);l=r+1){
r=min(n/(n/l),m/(m/l));
(ans+=(ask(r)-ask(l-1)+mod)%mod*(n/l)%mod*(m/l)%mod)%=mod;
}
qs[q[i].v]=ans;
}
for(int i=1;i<=t;++i)
printf("%lld\n",qs[i]);
return 0;
}