BZOJ4916 神犇和蒟蒻
题意:求miu[i*i]和phi[i*i]的前缀和。n <= 1e9
解:杜教筛。
第一问是搞笑的,答案是1。
第二问,发现phi[i*i] = phi[i] * i
这里杜教筛用的g(n) = n,h(n) = n2。
然后套路一波就没了。注意预处理的时候也要开long long
1 #include <cstdio> 2 #include <cstring> 3 4 typedef long long LL; 5 const int N = 1100010, T = 1100008; 6 const LL MO = 1e9 + 7, inv6 = 166666668; 7 8 int p[N], top, phi[N]; 9 LL F[N], F2[N], n, inv2; 10 bool vis[N]; 11 12 inline LL H(LL x) { 13 x %= MO; 14 return (x << 1 | 1) % MO * x % MO * (x + 1) % MO * inv6 % MO; 15 } 16 17 inline void getp(int n) { 18 phi[1] = 1; 19 for(int i = 2; i <= n; i++) { 20 if(!vis[i]) { 21 p[++top] = i; 22 phi[i] = i - 1; 23 } 24 for(int j = 1; j <= top && i * p[j] <= n; j++) { 25 vis[i * p[j]] = 1; 26 if(i % p[j] == 0) { 27 phi[i * p[j]] = phi[i] * p[j]; 28 break; 29 } 30 phi[i * p[j]] = phi[i] * (p[j] - 1); 31 } 32 } 33 for(int i = 1; i <= n; i++) { 34 F[i] = (F[i - 1] + 1ll * i * phi[i] % MO) % MO; 35 } 36 return; 37 } 38 39 LL solve(LL x) { 40 //printf("solve %lld \n", x); 41 if(x <= 0) return 0; 42 if(x <= T) return F[x]; 43 if(F2[n / x] != -1) return F2[n / x]; 44 //printf("solve %lld \n", x); 45 LL ans = H(x); 46 for(LL i = 2, j; i <= x; i = j + 1) { 47 j = x / (x / i); 48 ans -= (i + j) % MO * ((j - i + 1) % MO) % MO * inv2 % MO * solve(x / i) % MO; 49 ans = (ans % MO + MO) % MO; 50 } 51 return F2[n / x] = ans; 52 } 53 54 int main() { 55 inv2 = (MO + 1) / 2; 56 memset(F2, -1, sizeof(F2)); 57 getp(T); 58 scanf("%lld", &n); 59 printf("1\n%lld\n", solve(n)); 60 return 0; 61 }