题解:
Ans=∑ni=1∑i−1j=1i+j | i∗j
=∑nd=1∑n/di=1∑i−1j=1d(i+j) | i∗j∗d2(gcd(i,j)=1)
=∑nd=1∑n/di=1∑i−1j=1i+j | i∗j∗d(gcd(i,j)=1)
∵gcd(i,j)=1
∴gcd(i+j,i)=gcd(i+j,j)=1
∴gcd(i+j,i∗j)=1
∴原式
=∑nd=1∑n/di=1∑i−1j=1i+j | d(gcd(i,j)=1)
=∑ni=1∑i−1j=1[gcd(i,j)=1]∗∑n/id=1[i+j | d]
=∑ni=1∑i−1j=1[gcd(i,j)=1]∗⌊n/ii+j⌋
=∑ni=1∑i−1j=1⌊n/ii+j⌋∑d|gcd(i,j)μ(d)
=∑nd=1∑n/di=1∑i−1j=1⌊n/i/dd(i+j)⌋
=∑nd=1∑n/di=1∑i−1j=1⌊nd2∗i∗(i+j)⌋
=∑nd=1∑n/di=1∑2i−1j=i+1⌊nd2∗i∗j⌋
=∑n√d=1∑n/d/d√i=1∑2i−1j=i+1⌊nd2∗i∗j⌋
暴力枚举d,i,分块j,是可以过的。
复杂度不会证明。
Code:
#include<cmath>
#include<cstdio>
#define ll long long
#define fo(i, x, y) for(ll i = x; i <= y; i ++)
#define min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
const int N = 320000;
bool bz[N + 1]; int mu[N + 1], p[N];
ll n, ans;
int main() {
mu[1] = 1;
fo(i, 2, N) {
if(!bz[i]) p[++ p[0]] = i, mu[i] = -1;
fo(j, 1, p[0]) {
int k = i * p[j];
if(k > N) break;
bz[k] = 1;
if(i % p[j] == 0) {
mu[k] = 0; break;
}
mu[k] = -mu[i];
}
}
scanf("%lld", &n);
fo(d, 1, sqrt(n * 1.0)) if(mu[d]){
ll m = n / d / d;
fo(j, 2, sqrt(m * 1.0)) {
ll z = m / j;
fo(i, j + 1, 2 * j - 1) {
if(z / i == 0) break;
ll k = min(z / (z / i), 2 * j - 1);
ans += (z / i) * (k - i + 1) * mu[d];
i = k;
}
}
}
printf("%lld", ans);
}