题目传送门
题意:
给你一个 n ( 1 ≤ n ≤ 2 ∗ 1 0 6 ) n(1\le n\le 2*10^6) n(1≤n≤2∗106),求 ∑ i = 1 n ∑ j = i + 1 n g c d ( i , j ) \sum\limits_{i=1}^{n}\sum\limits_{j=i+1}^{n}gcd(i,j) i=1∑nj=i+1∑ngcd(i,j)。
思路:
稍微对这个式子改写一下,变成了 ∑ i = 1 n ∑ j = 1 n g c d ( i , j ) − ( 1 + n ) ∗ n 2 2 \cfrac{\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}gcd(i,j)-\cfrac{(1+n)*n}{2}}{2} 2i=1∑nj=1∑ngcd(i,j)−2(1+n)∗n。
我们只研究式子 ∑ i = 1 n ∑ j = 1 n g c d ( i , j ) \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}gcd(i,j) i=1∑nj=1∑ngcd(i,j)就行了。
∑ i = 1 n ∑ j = 1 n g c d ( i , j ) = ∑ g = 1 n ∑ i = 1 n ∑ j = 1 n [ g c d ( i , j ) = g ] ∗ g = ∑ g = 1 n ∑ i = 1 ⌊ n g ⌋ ∑ j = 1 ⌊ n g ⌋ [ g c d ( i , j ) = 1 ] ∗ g = ∑ g = 1 n ∑ i = 1 ⌊ n g ⌋ ∑ j = 1 ⌊ n g ⌋ ∑ d ∣ ( i , j ) μ ( d ) ∗ g = ∑ g = 1 n ∑ d ∣ ( i , j ) μ ( d ) ⌊ n g d ⌋ 2 ∗ g \begin{aligned} \\ &\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}gcd(i,j)\\ =&\sum\limits_{g=1}^{n}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}[gcd(i,j)=g]*g\\ =&\sum\limits_{g=1}^{n}\sum\limits_{i=1}^{\lfloor \frac{n}{g}\rfloor}\sum\limits_{j=1}^{\lfloor \frac{n}{g}\rfloor}[gcd(i,j)=1]*g\\ =&\sum\limits_{g=1}^{n}\sum\limits_{i=1}^{\lfloor \frac{n}{g}\rfloor}\sum\limits_{j=1}^{\lfloor \frac{n}{g}\rfloor}\sum\limits_{d|(i,j)}\mu(d)*g\\ =&\sum\limits_{g=1}^{n}\sum\limits_{d|(i,j)}\mu(d)\lfloor\cfrac{n}{gd}\rfloor^2*g \end{aligned} ====i=1∑nj=1∑ngcd(i,j)g=1∑ni=1∑nj=1∑n[gcd(i,j)=g]∗gg=1∑ni=1∑⌊gn⌋j=1∑⌊gn⌋[gcd(i,j)=1]∗gg=1∑ni=1∑⌊gn⌋j=1∑⌊gn⌋d∣(i,j)∑μ(d)∗gg=1∑nd∣(i,j)∑μ(d)⌊gdn⌋2∗g
然后就可以整除分块求答案了。
C o d e Code Code
// Author : ACfunhsl
// Time : 2021/5/17 14:13:11
#define int long long
const int N = 2e6+50;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
bool ok[N];
int p[N],cnt=0,mu[N];
void euler()
{
mu[1] = 1;
for(int i=2; i<N; i++)
{
if(!ok[i])
{
p[++cnt] = i;
mu[i] = -1;
}
for(int j=1; j<=cnt&&i*p[j]<N; j++)
{
ok[i*p[j]] = 1;
if(i%p[j]==0) break;
mu[i*p[j]] = -mu[i];
}
}
for(int i=1; i<N; i++)
mu[i] += mu[i-1];
}
int cal(int n,int k)
{
int res = 0;
n/=k;
for(int l=1,r; l<=n; l=r+1)
{
r = n/(n/l);
res += (n/l)*(n/l)*(mu[r] - mu[l-1]);
}
return res;
}
signed main()
{
euler();
int n;
cin>>n;
int res = 0;
for(int i=1;i<=n;i++)
res += cal(n,i)*i;
res -= (1+n)*n/2;
res /= 2;
cout<<res<<endl;
return 0;
}