原题链接:https://ac.nowcoder.com/acm/contest/8282/D
∑ i = 1 n ∑ j = 1 n μ ( i j ) \sum_{i=1}^{n}\sum_{j=1}^{n}\mu(ij) i=1∑nj=1∑nμ(ij)
= ∑ i = 1 n ∑ j = 1 n μ ( i ) μ ( j ) [ g c d ( i , j ) = 1 ] =\sum_{i=1}^{n}\sum_{j=1}^{n}\mu(i)\mu(j)[gcd(i,j)=1] =i=1∑nj=1∑nμ(i)μ(j)[gcd(i,j)=1]
= ∑ i = 1 n ∑ j = 1 n μ ( i ) μ ( j ) ∑ t ∣ i , t ∣ j μ ( t ) =\sum_{i=1}^{n}\sum_{j=1}^{n}\mu(i)\mu(j)\sum_{t|i,t|j}\mu(t) =i=1∑nj=1∑nμ(i)μ(j)t∣i,t∣j∑μ(t)
= ∑ t = 1 n μ ( t ) ∑ i = 1 n / t ∑ j = 1 n / t μ ( i t ) μ ( j t ) =\sum_{t=1}^{n}\mu(t)\sum_{i=1}^{n/t}\sum_{j=1}^{n/t}\mu(it)\mu(jt) =t=1∑nμ(t)i=1∑n/tj=1∑n/tμ(it)μ(jt)
= ∑ t = 1 n μ ( t ) ∑ i = 1 n / t μ ( i t ) ∑ j = 1 n / t μ ( j t ) =\sum_{t=1}^{n}\mu(t)\sum_{i=1}^{n/t}\mu(it)\sum_{j=1}^{n/t}\mu(jt) =t=1∑nμ(t)i=1∑n/tμ(it)j=1∑n/tμ(jt)
设 F ( n , t ) = ∑ i = 1 n / t μ ( i t ) 设F(n,t)=\sum_{i=1}^{n/t}\mu(it) 设F(n,t)=i=1∑n/tμ(it)
= ∑ t = 1 n μ ( t ) F ( n , t ) 2 =\sum_{t=1}^{n}\mu(t)F(n,t)^2 =t=1∑nμ(t)F(n,t)2
到这里如果直接算是可以Tnlogn的,但考虑到有T组数据,所以预处理出所有答案,然后O(1)输出
换个角度,考虑每个F对答案的贡献,我们发现有些时候,n/t不同的n答案有时也是一样的,所以我们对于算出n的两端取值进行差分,O(nlogn)的复杂度
#include
using namespace std;
#define fi first
#define se second
typedef long long ll;
typedef pair<int, int> PII;
const int N = 2e6 + 100, M = 5e5 + 5, INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
ll prime[N], mu[N], k, ans[N];
bool is_prime[N];
inline void init(int n) {
memset(is_prime, true, sizeof is_prime);
mu[1] = 1;
for (int i = 2; i < n; ++i) {
if (is_prime[i]) prime[++k] = i, mu[i] = -1;
for (int j = 1; j <= k && i * prime[j] < n; ++j) {
is_prime[i * prime[j]] = false;
if (i % prime[j] == 0) {
break;
} else {
mu[i * prime[j]] = -mu[i];
}
}
}
for (int t = 1; t < n; t++) {
ll tmp = 0;
for (int i = t; i < n; i += t) {
tmp += mu[i];
int l = i;
int r = min(n, l + t - 1);
ans[l] += mu[t] * tmp * tmp;
ans[r + 1] -= mu[t] * tmp * tmp;
}
}
for (int i = 1; i < n; i++) ans[i] = ans[i-1] + ans[i];
}
void solve() {
init(N);
int T; cin >> T; while (T--) {
int n; cin >> n;
printf("%lld\n", ans[n]);
}
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
}