HDU5608 function

解:顯然f那個式子能夠反演一波,而後再推一波,最後出來了這個......ide

其中M是莫比烏斯函數的前綴和。雖然看起來能算...感受很毒瘤,複雜度也不會。函數

正解:杜教篩的套路是對一個卷函數求前綴和,而後拆開。spa

因而咱們直接對(i2 - 3i + 2)求前綴和,以後就是一個很普通的杜教篩式子了......code

如何預處理f?利用反演式子,考慮每一個(i2 - 3i + 2)會對哪些f有所貢獻便可。複雜度調和級數。blog

注意long long和取模...我全程爆炸調了一夜。get

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <cstring>
 4 #include <map>
 5 
 6 typedef long long LL;
 7 const int N = 1000010, T = 1000008;
 8 const LL MO = 1e9 + 7, inv6 = 166666668, inv2 = 500000004, INF = 0x7f7f7f7f7f7f7f7fll;
 9 
10 int miu[N], p[N], top;
11 LL F[N], n;
12 std::map<LL, LL> F2;
13 bool vis[N];
14 
15 inline LL qpow(LL a, LL b) {
16     LL ans = 1;
17     while(b) {
18         if(b & 1) ans = ans * a % MO;
19         a = a * a % MO;
20         b = b >> 1;
21     }
22     return ans;
23 }
24 
25 inline LL G(LL x) {
26     x %= MO;
27     return (((x * 2 + 1) % MO) * inv6 % MO * x % MO * ((x + 1) % MO) % MO -
28     ((x + 1) % MO) * inv2 % MO * x % MO * 3 % MO + x * 2 % MO) % MO;
29 }
30 
31 inline LL g(LL x) {
32     x %= MO;
33     return (x * x % MO - 3 * x % MO + 2 + MO) % MO;
34 }
35 
36 inline void prework() {
37     /// get miu
38     miu[1] = 1;
39     for(int i = 2; i <= T; i++) {
40         if(!vis[i]) {
41             p[++top] = i;
42             miu[i] = -1;
43         }
44         for(int j = 1; j <= top && i * p[j] <= T; j++) {
45             vis[i * p[j]] = 1;
46             if(i % p[j] == 0) break;
47             miu[i * p[j]] = -miu[i];
48         }
49     }
50     /// getF
51     for(int i = 1; i <= T; i++) {
52         LL t = g(i);
53         for(int j = 1; i * j <= T; j++) {
54             F[i * j] += t * miu[j] % MO;
55             F[i * j] = (F[i * j] % MO + MO) % MO;
56         }
57     }
58     for(int i = 1; i <= T; i++) {
59         F[i] = (F[i] + F[i - 1]) % MO;
60     }
61     return;
62 }
63 
64 LL solve(LL x) {
65     if(x <= 0) return 0;
66     if(x <= T) return F[x];
67     if(F2.count(x)) return F2[x];
68     LL ans = G(x);
69     for(LL i = 2, j; i <= x; i = j + 1) {
70         j = x / (x / i);
71         ans -= solve(x / i) * (j - i + 1) % MO;
72         ans = (ans % MO + MO) % MO;
73     }
74     return F2[x] = ans;
75 }
76 
77 int main() {
78     int q;
79     scanf("%d", &q);
80     prework();
81     //printf("q = %d \n", q);
82     for(int i = 1; i <= q; i++) {
83         //printf("i = %d q = %d \n", i, q);
84         scanf("%lld", &n);
85         printf("%lld\n", solve(n));
86     }
87     return 0;
88 }
AC代碼
相關文章
相關標籤/搜索