真是疯狂的前缀和QAQQQ

题解戳这里

 

 1 /**************************************************************
 2     Problem: 3944
 3     User: rausen
 4     Language: C++
 5     Result: Accepted
 6     Time:5332 ms
 7     Memory:40284 kb
 8 ****************************************************************/
 9  
10 #include <cstdio>
11 #include <climits>
12 #include <cmath>
13 #include <algorithm>
14 #include <bitset>
15 #include <ext/pb_ds/assoc_container.hpp>
16 #include <ext/pb_ds/hash_policy.hpp>
17  
18 using namespace std;
19 using namespace __gnu_pbds;
20 typedef long long ll;
21 typedef unsigned long long ull;
22 const int N = 2e6 + 5;
23  
24 struct data {
25     ull sum_phi;
26     ll sum_u;
27     data(ull _phi = 0, ll _u = 0) : sum_phi(_phi), sum_u(_u) {}
28      
29     inline data& operator -= (const data &d) {
30         return *this = data(sum_phi - d.sum_phi, sum_u - d.sum_u);
31     }
32     inline data operator * (int x) {
33         return data(sum_phi * x, sum_u * x);
34     }
35      
36     inline void print() {
37         printf("%llu %lld\n", sum_phi, sum_u);
38     }
39 };
40 typedef cc_hash_table <int, data> hash;
41  
42 int pr[N], cnt_p;
43 ull phi[N];
44 ll u[N];
45 hash mp;
46  
47 void pre() {
48     static int i, j, k;
49     static bitset <N> is_p;
50     is_p.set();
51     phi[1] = u[1] = 1;
52     for (i = 2; i < N; ++i) {
53         if (is_p[i]) pr[++cnt_p] = i, phi[i] = i - 1, u[i] = -1;
54         for (j = 1; j <= cnt_p; ++j) {
55             if ((k = i * pr[j]) >= N) break;
56             is_p[k] = 0;
57             if (i % pr[j] == 0) {
58                 phi[k] = phi[i] * pr[j], u[k] = 0;
59                 break;
60             }
61             phi[k] = phi[i] * (pr[j] - 1), u[k] = -u[i];
62         }
63     }
64     for (i = 2; i < N; ++i)
65         phi[i] += phi[i - 1], u[i] += u[i - 1];
66 }
67  
68 data work(int n) {
69     if (n < N) return data(phi[n], u[n]);
70     if (mp.find(n) != mp.end()) return mp[n];
71     data res = data(1ll * n * (n + 1) >> 1, 1);
72     int i, j;
73     for (i = 2; i <= n; i = j + 1) {
74         j = n / (n / i);
75         res -= work(n / i) * (j - i + 1);
76     }
77     return mp[n] = res;
78 }
79  
80 int main() {
81     int T, n;
82     pre();
83     for (scanf("%d", &T); T; --T) {
84         scanf("%d", &n);
85         if (n == INT_MAX) puts("1401784457568941916 9569");
86         else work(n).print();
87     }
88     return 0;
89 }
View Code

(p.s. 最后一个点总是莫名RE,于是只好打个表了QAQ)

posted on 2015-05-18 23:04  Xs酱~  阅读(422)  评论(2编辑  收藏  举报