题面
求\(\sum_{i=1}^{n-1}\sum_{j=i+1}^{n}gcd(i, j)\)
n<=4000000,数据组数T<=100 答案保证在64位带符号整数范围内(long long就好)Sol
先不管i,j是否有序,我们就求\(\sum_{i=1}^{n}\sum_{j=1}^{n}gcd(i, j)\) 最后\(ans=(ans - (n + 1) * n / 2) / 2\)即可 推导\(ans=\sum_{d=1}^{n}\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\mu(i)*\lfloor\frac{n}{i*d}\rfloor^2\)\(用k替换i*d,ans=\sum_{k=1}^{n}\lfloor\frac{n}{k}\rfloor^2\sum_{d|k}\mu(\frac{k}{d})d\)\(\sum_{d|k}\mu(\frac{k}{d})d\)是积性函数,线性筛即可 加上数论分块# include# define RG register# define IL inline# define Zsydalao 666# define Fill(a, b) memset(a, b, sizeof(a))using namespace std;typedef long long ll;const int _(4e6 + 1); IL ll Read(){ char c = '%'; ll x = 0, z = 1; for(; c > '9' || c < '0'; c = getchar()) if(c == '-') z = -1; for(; c >= '0' && c <= '9'; c = getchar()) x = x * 10 + c - '0'; return x * z;} int prime[_], num;ll f[_];bool isprime[_]; IL void Prepare(){ isprime[1] = 1; f[1] = 1; for(RG int i = 2; i < _; ++i){ if(!isprime[i]) prime[++num] = i, f[i] = i - 1; for(RG int j = 1; j <= num && i * prime[j] < _; ++j){ isprime[i * prime[j]] = 1; if(i % prime[j]) f[i * prime[j]] = f[i] * f[prime[j]]; else{ f[i * prime[j]] = f[i] * prime[j]; break; } } } for(RG int i = 2; i < _; ++i) f[i] += f[i - 1];} int main(RG int argc, RG char *argv[]){ Prepare(); while(Zsydalao == 666){ RG ll n = Read(), ans = 0; if(!n) break; for(RG ll k = 1, j; k <= n; k = j + 1){ j = n / (n / k); ans += (n / k) * (n / k) * (f[j] - f[k - 1]); } printf("%lld\n", (ans - n * (n + 1) / 2) / 2); } return 0;}