P8570 [JRKSJ R6] 牵连的世界 题解
推式子萌新来推推看式子。
\[\sum_{i=1}^n\sum_{j=1}^m\sigma(ij)\varphi(ij)
\]
先把 \(\sigma\) 和 \(\varphi\) 展开来。
\[\sum_{i=1}^n\sum_{j=1}^m\dfrac{\varphi(i)\varphi(j)\gcd(i,j)}{\varphi(\gcd(i,j))}\sum_{x|i}\sum_{y|j}[\gcd(x,y)=1]
\]
替换 \([\gcd(x,y)]=1\)。
\[\sum_{i=1}^n\sum_{j=1}^m\dfrac{\varphi(i)\varphi(j)\gcd(i,j)}{\varphi(\gcd(i,j))}\sum_{x|i}\sum_{y|j}\sum_{d|x,d|y}\mu(d)
\]
换个枚举顺序,把 \(d\) 的枚举提前。
\[\sum_{i=1}^n\sum_{j=1}^m\dfrac{\varphi(i)\varphi(j)\gcd(i,j)}{\varphi(\gcd(i,j))}\sum_{d|\gcd(i,j)}\sigma(\frac{i}{d})\sigma(\frac{j}{d})\mu(d)
\]
再换个枚举顺序,把 \(d\) 的枚举再提前。
\[\sum_{d=1}^n\sum_{i=1}^{n/d}\sum_{j=1}^{m/d}\dfrac{\varphi(id)\varphi(jd)\gcd(i,j)d}{\varphi(\gcd(i,j)d)}\sigma(i)\sigma(j)\mu(d)
\]
枚举 \(z=\gcd(i,j)\)。
\[\sum_{d=1}^n\mu(d)d\sum_{z=1}^{n/d}\sum_{i=1}^{n/dz}\sum_{j=1}^{m/dz}\dfrac{\varphi(idz)\varphi(jdz)z}{\varphi(zd)}\sigma(iz)\sigma(jz)[\gcd(i,j)=1]
\]
换个顺序。
\[\sum_{d=1}^n\mu(d)d\sum_{z=1}^{n/d}\dfrac{z}{\varphi(zd)}\sum_{i=1}^{n/dz}\sigma(iz)\varphi(idz)\sum_{j=1}^{m/dz}\sigma(jz)\varphi(jdz)[\gcd(i,j)=1]
\]
再替换 \([\gcd(i,j)=1]\)。
\[\sum_{d=1}^n\mu(d)d\sum_{z=1}^{n/d}\dfrac{z}{\varphi(zd)}\sum_{i=1}^{n/dz}\sigma(iz)\varphi(idz)\sum_{j=1}^{m/dz}\sigma(jz)\varphi(jdz)\sum_{w|i,w|j}\mu(w)
\]
把 \(w\) 放到前面枚举。
\[\sum_{d=1}^n\mu(d)d\sum_{z=1}^{n/d}\dfrac{z}{\varphi(zd)}\sum_{w=1}^{n/dz}\mu(w)\sum_{i=1}^{n/dzw}\sigma(iwz)\varphi(iwdz)\sum_{j=1}^{m/dzw}\sigma(jwz)\varphi(jwdz)
\]
定义两个函数:
\[A(x,y)=\sum_{i=1}^{n/xy}\sigma(iy)\varphi(ixy)
\]
\[B(x,y)=\sum_{i=1}^{m/xy}\sigma(iy)\varphi(ixy)
\]
原式可以转化为:
\[\sum_{d=1}^n\mu(d)d\sum_{z=1}^{n/d}\dfrac{z}{\varphi(zd)}\sum_{w=1}^{n/dz}\mu(w)A(d,zw)B(d,zw)
\]
首先可以发现:乘积小于等于 \(n\) 的三元组个数是 \(O(n\log^2 n)\) 级别的。所以我们可以在 \(O(n\log ^2 n)\) 的时间复杂度内计算出所有 \(A(x,y)\) 和 \(B(x,y)\)。
如果已经算出了 \(A\) 和 \(B\),剩下的按照上面的式子算,容易发现也是 \(O(n\log^2 n)\) 的。所以我们用 \(O(n\log^2 n)\) 完成了这道题。
// mu 表示莫比乌斯函数,phi 表示欧拉函数,D 表示约束个数和函数,inv 表示逆元
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> m;
init();
ll ans=0;
for (int d=1;d<=n;d++)
{
for (int j=1;j<=n/d;j++)
{
a[j]=0;
for (int i=1;i<=n/(d*j);i++) a[j]=(a[j]+1ll*D[i*j]*phi[i*d*j]%mod)%mod;
b[j]=0;
for (int i=1;i<=m/(d*j);i++) b[j]=(b[j]+1ll*D[i*j]*phi[i*d*j]%mod)%mod;
}
for (int j=1;j<=n/d;j++)
{
for (int w=1;w<=n/(d*j);w++)
{
ans=ans+1ll*mu[d]*mu[w]*inv[phi[j*d]]*d%mod*j%mod*a[j*w]%mod*b[j*w]%mod;
ans=(ans+mod)%mod;
}
}
}
cout << ans;
return 0;
}