【题解】LOJ #6052 「雅礼集训 2017 Day11」DIV【莫比乌斯反演】
题意
定义 \(a\mathrm i+b\) 是 \(n\) 的约数当且仅当存在 \(c\mathrm i +d\) 使得 \((a\mathrm i +b)(c\mathrm i +d)=n(a,b,c,d\in \mathbf{N})\)。
设 \(h(n)\) 为 \(n\) 的约数的实部之和,要求实部大于 \(0\)。求 \(H(n)=\sum_i^n h(i)\)。\(n\leq 10^{10}\)。
题解
先考虑虚部大于 \(0\) 的情况。设 \(n=(a\mathrm i +b)(c\mathrm i d)(a>0)\),则 \(ac-bd=n,ad+bc=0\)。设:
\[\begin{aligned}
a=px\\
p=qx\\
c=py\\
d=-qy\\
p\bot q
\end{aligned}
\]
则 \((p,q,x,y)\) 唯一确定 \((a,b,c,d)\)。
记:
-
\[g(n)=\sum_{p^2+q^2=n} [p\bot q]p \]
-
\[f(n)=\sum_{p^2+q^2=n}p \]
-
\[S(n)=\sum_{i=1}^{n}\sigma_1(i) \]
问题化为:
\[\begin{aligned}
&\sum_{p,q,x,y}[p\bot q][xy(p^2+q^2)\leq n]px\\
=&\sum_{i=1}^{n} \left(\sum_{p^2+q^2=i}[p\bot q]p\right)+\left(\sum_{xy\leq n /i}x\right)\\
=&\sum_{i=1}^{n}g(i)S(\lfloor \dfrac{x}{i}\rfloor)
\end{aligned}
\]
\(S(n)\) 在小数据处线性筛预处理,大数据处整除分块。
\[\begin{aligned}
\sum_{i=1}^n g(i)=&\sum_{p^2+q^2\leq n}[p\bot q]p\\
&\sum_{i=1}^{\sqrt n}i\mu(i)\sum_{j=1}^{\lfloor \frac{n}{i^2}\rfloor}f(j)
\end{aligned}
\]
\(g\) 的前缀和暴力计算,\(f\) 的前缀和可以暴力枚举 \(p\)。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int M1=1.2e5,M2=5e6,mod=1004535809,inv2=(mod+1)/2;
bool boo[M2];
int sig[M2],mu[M2],pri[M2],r[M2],cnt;
struct IZHR2MJy{
int lim=0;
void init(int n){
sig[1]=1;
mu[1]=1;
lim=n;
for(int i=2;i<=n;i++){
if(!boo[i]){
r[i]=1;
sig[i]=i+1;
pri[cnt++]=i;
mu[i]=-1;
}
for(int j=0;j<cnt&&i*pri[j]<=n;j++){
int v=i*pri[j];
boo[v]=1;
if(i%pri[j]){
sig[v]=sig[i]*1ll*sig[pri[j]]%mod;
mu[v]=-mu[i];
r[v]=i;
}else{
sig[v]=(sig[i]*1ll*pri[j]+sig[r[i]])%mod;
r[v]=r[i];
break;
}
}
}
for(int i=1;i<=n;i++)sig[i]=(sig[i-1]+sig[i])%mod;
}
int _(ll x){
x%=mod;
return x*(x+1)/2%mod;
}
int operator()(ll x){
if(x<=lim)return sig[x];
int ans=0;
for(ll l=1,r;l<=x;l=r+1){
r=x/(x/l);
int t=x/l%mod;
ans=(ans+(_(r)-_(l-1)+mod)*1ll*t)%mod;
}
return ans;
}
}S;
int F(ll n){
int ans=0;
for(ll i=1;i*i<=n;i++)
ans=(ans+i*int(sqrt(n-i*i)))%mod;
return ans;
}
int G(ll n){
int lsti=-1,lstf=0,ans=0;
for(ll i=1;i*i<=n;i++){
if(n/i/i!=lsti){
lsti=n/i/i;
lstf=F(n/i/i);
}
ans=(ans+mu[i]*i*lstf)%mod;
}
return ans;
}
int main(){
ll n;
scanf("%lld",&n);
S.init(pow(n,0.667));
int ans=0;
for(ll l=1,r,sl=0;l<=n;l=r+1){
r=n/(n/l);
int sr=G(r);
ans=(ans+(sr-sl)*1ll*S(n/l))%mod;
sl=sr;
}
cout<<((ans+mod)*2ll+S(n))%mod<<endl;
}