[ACM][2018南京預賽]Sum

1、題面函數

 

樣例輸入:spa

2code

5 8blog

樣例輸出:it

8io

14class

 

2、思路基礎

關鍵詞:線性篩im

在Zed的幫助下知道了這是一道線性篩的比較裸的題了。考試過程當中肝這道題的時間最久,費了心思找到遞推式後,發現根本不是在1s內能實現的東西。考試過程當中大三學長選擇了暴力打表打了幾十KB。。。考後向Zed請教良久知道了線性篩。線性篩最基礎的做用是篩出全部質數,時間複雜度僅爲o(n)。因爲f(x)是「積性函數」(f(a * b) = f(a) * f(b)),因此也能夠用線性篩處理。img

 

3、代碼

 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 }
相關文章
相關標籤/搜索