2018 南京网络预赛Sum ——莫比乌斯反演

题意

设 $f(n)$ 为 $n=ab$ 的方案数,其中 $a,b$ 为无平方因子数。求 $displaystyle  sum_{i=1}^nf(i)$,$n leq 2e7$。

分析

显然,可发现 $f = mu ^2 * mu ^2$.

即 $displaystyle f(n) = sum_{d | n} mu^2(d) mu^2(frac{n}{d})$

那么可以这样化简目标式

$$egin{aligned} & sum_{i = 1}^{n} f(i) \ =& sum_{i = 1}^{n} sum_{d | i} mu^2 (d) mu^2 (frac{i}{d}) \ =& sum_{d = 1}^{n} sum_{d | i}^{1leq i leq n} mu^2(d) mu^2(frac{i}{d}) \ = & sum_{d = 1}^{n} mu^2 (d) sum_{i = 1}^{lfloor frac{n}{d} floor} mu^2 (i) end{aligned}$$

那么重点在于预处理出 $mu^2$ 的前缀和,然后整除分块一下就可以了。

这里预处理的复杂度为 $O(n)$(可以用这一结论 $displaystyle sum_{i=1}^n mu (i)^2 = sum_{i=1}^{left lfloor sqrt n ight floor}mu (i)left lfloor frac{n}{i^2} ight floor$ 降至 $O(sqrt n)$),单次询问的复杂度为 $O(sqrt n)$

数组全用 long long 会MLE。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn = 2e7 + 10;
int p[maxn], flg[maxn], mu[maxn];
ll sum_mu[maxn];
int n;

void init(int N) {
  int tot = 0;
  mu[1] = 1;
  for (int i = 2; i <= N; ++i) {
    if (!flg[i]) {
      p[++tot] = i;
      mu[i] = -1;
    }
    for (int j = 1; j <= tot && i * p[j] <= N; ++j) {
      flg[i * p[j]] = 1;
      if (i % p[j] == 0) {
        mu[i * p[j]] = 0;
        break;
      }
      mu[i * p[j]] = -mu[i];
    }
  }
  for (int i = 1; i <= N; ++i)sum_mu[i] = sum_mu[i-1] + mu[i]*mu[i];
}

int main()
{
   init(2e7);
   int T;
   scanf("%d", &T);
   while(T--)
   {
       scanf("%d", &n);
        ll ans = 0;
        for(int l=1, r;l <= n;l = r+1)
        {
            r = n / (n/l);
            ans += sum_mu[n/l] * (sum_mu[r] - sum_mu[l-1]);
        }
       printf("%lld
", ans);
   }
   return 0;
}

参考链接:

1. http://www.cfzhao.com/2019/05/23/%E8%AE%A1%E8%92%9C%E5%AE%A2-a1956-sum/

2. 一道积性函数求和题(知乎)

原文地址:https://www.cnblogs.com/lfri/p/11382166.html