Luogu P1390 公约数的和
gate
求:
设\(gcd(i,j) = k\),枚举\(k\)
同时除以\(k\)
根据
\(\begin{array} \ \because \sum\limits_{d∣n}\mu(d)=[n=1] \\ \therefore \sum\limits_{d∣gcd(i,j)}μ(d) = [gcd(i,j)=1] \end{array}\)
把\([gcd(i,j)=1]\)替换掉
将\(d\)提前,同时把\(i,j\)除以\(d\)
整除分块
设\(T=kd\)
把\(d\)换成\(T\)
\(k\)也就是\(id(k)\),可以写成
因为\(k*\frac{T}{k} = T\),所以在枚举\(T\)时,\(k\)和\(\frac{T}{k}\)可以看成相同的元素,只是顺序相反
\(\begin{array} \ \because id*\mu=\varphi \\ \therefore \sum\limits_{k|T}id(k)\mu(\frac{T}{k}) = \sum\limits_{k|T}\varphi(k) \end{array}\)
\(\because \varphi\)是积性函数
\(\therefore \sum\limits_{k|T}\varphi(k) = \varphi(T)\)
即原式可以转化为
莫比乌斯反演的部分到此结束了,但注意,题目要求的是\([1,n]\)中每任意两个不同的数的\(gcd\)之和,
而上述做法多加了\(gcd(i,i)\),且重复计算了\(gcd(i,j)\)和\(gcd(j,i)\)
所以我们要把多余的部分减去,最终答案即 \((Ans-\sum\limits_{i=1}^ni)/2\)
也就是等差数列,可以写成\((Ans-(1+n)*n/2)/2\)
代码如下
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define MogeKo qwq
using namespace std;
const int maxn = 2e6+5;
long long n,p[maxn];
void get_phi(long long n) {
for(long long i = 1; i <= n; i++)
p[i] = i;
for(long long i = 2; i <= n; i++)
if(p[i] == i)
for(long long j = i; j <= n; j += i)
p[j] = p[j]/i*(i-1);
for(long long i = 1; i <= n; i++)
p[i] += p[i-1];
}
long long calc(long long n,long long m) {
long long ans = 0;
long long r = 0;
for(long long i = 1; i <= n; i = r+1) {
r = min(n/(n/i),m/(m/i));
ans += (p[r]-p[i-1]) * (n/i) * (m/i);
}
return ans;
}
int main() {
scanf("%lld",&n);
get_phi(n);
printf("%lld",(calc(n,n)-(1+n)*n/2)/2);
return 0;
}