[2018南京预赛]Sum
一、题面
样例输入:
2
5 8
样例输出:
8
14
二、思路
关键词:线性筛
在Zed的帮助下知道了这是一道线性筛的比较裸的题了。考试过程中肝这道题的时间最久,费了心思找到递推式后,发现根本不是在1s内能实现的东西。考试过程中大三学长选择了暴力打表打了几十KB。。。考后向Zed请教良久知道了线性筛。线性筛最基础的作用是筛出所有质数,时间复杂度仅为o(n)。由于f(x)是“积性函数”(f(a * b) = f(a) * f(b)),所以也可以用线性筛处理。
三、代码
1 #include <cstdio> 2 #include <algorithm> 3 #include <cmath> 4 using namespace std; 5 6 #define MAXN 200005 7 #define MAXT 25 8 9 int T, a[MAXT], n, tot, g[MAXN], p[MAXN], s[MAXN], f[MAXN], v[MAXN]; 10 11 void work() { 12 f[1] = 1, s[1] = 1; 13 for (int i = 2; i <= n; i++) { 14 if (!v[i]) p[++tot] = i, f[i] = 2; 15 for (int j = 1; j <= tot; j++) { 16 int k = i * p[j]; 17 if (k > n) break; 18 v[k] = 1; 19 if (!(i % p[j])) { 20 f[k] = g[i] ? 0 : f[i] / 2; 21 g[k] = 1; 22 break; 23 } 24 else f[k] = f[i] * 2; 25 } 26 s[i] = s[i - 1] + f[i]; 27 } 28 } 29 30 int main() { 31 scanf("%d", &T); 32 for (int i = 1; i <= T; i++) scanf("%d", &a[i]), n = max(a[i], n); 33 work(); 34 for (int i = 1; i <= T; i++) printf("%d\n", s[a[i]]); 35 return 0; 36 }