[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 }

 

posted @ 2018-09-05 19:57  jinkun113  阅读(202)  评论(0编辑  收藏  举报