2018 南京网络预赛Sum - 线性筛
题意
定义 $f(x)$ 为满足以下条件的有序二元组 $(a, b)$ 的方案数(即 $(a, b)$ 与 $(b, a)$ 被认为是不同的方案):
- $x= ab$
- $a$ 和 $b$ 均无平方因子(即因子中没有除1之外的完全平方数)
求 $\displaystyle \sum_{i=1}^nf(i), 1 \leq n\leq 2 \times 10^7$.
分析
显然,$f(n)$ 是积性函数,考虑线性筛。
- 当 $x$为素数时, $f(x)=2$,即 $(1,x)$ 和 $(x,1)$;
- 当 $x$ 的最小质因子为 $p$,且 $p \nmid \frac{x}{p}$ 时,$f(x) = f(p)f(\frac{x}{p}) = 2f(\frac{x}{p})$;
- 当 $x$ 的最小的质因数为 $p$,且 $p \mid \frac{x}{p}$
- 如果 $p \mid \frac{x}{p^2}$,那么 $x$ 中的 $p$ 的指数至少为3,即不管如何划分 $(a, b)$,两个数中一定有一个数其 $p$ 的指数大于等于2,即不存在合法的方案
- 否则, $x$中 $p$ 的指数就为2,把这两个 $p$ 分别分给 $a$ 和 $b$,剩余的 $\frac{x}{p^2}$就是一个子问题,即 $f(x) = f(\frac{x}{p^2}) = f(\frac{x}{p})f(\frac{1}{p}) = f(\frac{x}{p})/2$
#include<bits/stdc++.h> using namespace std; const int maxn = 2e7 + 10; int n; int vis[maxn], primes[maxn], primeCnt; int f[maxn], s[maxn]; //f(i)的前缀和 void seive() { f[1] = 1; for(int i = 2;i <= maxn;i++) { if(!vis[i]) { primes[++primeCnt] = i; f[i] = 2; } for(int j=1;j <= primeCnt && (long long)i * primes[j] <= maxn;j++) { vis[i *primes[j]] = true; if(i % primes[j] == 0) { f[i *primes[j]] = (i / primes[j] % primes[j] == 0)? 0: f[i/primes[j]]; break; } else f[i * primes[j]] = f[i] * 2; } } } int main() { seive(); for(int i = 1;i <= maxn;i++) s[i] = s[i-1]+f[i]; int T; scanf("%d", &T); while(T--) { scanf("%d", &n); printf("%d\n", s[n]); } }
参考链接:https://oi.men.ci/jsk-30999/#%D0%B4%D0%B0%D0%BB%D0%B5%D0%B5
个性签名:时间会解决一切