解:显然f那个式子可以反演一波,然后再推一波,最后出来了这个......
其中M是莫比乌斯函数的前缀和。虽然看起来能算...感觉很毒瘤,复杂度也不会。
正解:杜教筛的套路是对一个卷函数求前缀和,然后拆开。
于是我们直接对(i2 - 3i + 2)求前缀和,之后就是一个很普通的杜教筛式子了......
如何预处理f?利用反演式子,考虑每个(i2 - 3i + 2)会对哪些f有所贡献即可。复杂度调和级数。
注意long long和取模...我全程爆炸调了一晚上。
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 ", q); 82 for(int i = 1; i <= q; i++) { 83 //printf("i = %d q = %d ", i, q); 84 scanf("%lld", &n); 85 printf("%lld ", solve(n)); 86 } 87 return 0; 88 }