hdu 5382 GCD?LCM! - 莫比乌斯反演
题目传送门
题目大意
设$F(n) = \sum_{i = 1}^{n}\sum_{j = 1}^{n}\left [ [i, j] + (i, j) \geqslant n \right ]$,求$\sum_{i = 1}^{n} F(i)$。
考虑设$f(n) = \sum_{i = 1}^{n}\sum_{i = 1}^{n}\left[ \left[i,j \right ] + (i, j) = n \right ]$,那么有$F(n) = F(n - 1) - f(n - 1) + 2n - 1$。(因为$[i, n]\geqslant n$)
显然$[i, j] = k(i, j)$,那么我们可以枚举最大公约数。
$f(n)=\sum_{d \mid n}\sum_{i = 1}^{n}\sum_{j = 1}^{n}[(i, j) = 1][[id, jd] +d = n]\\=\sum_{d \mid n}\sum_{i = 1}^{n}\sum_{j = 1}^{n}[(i, j) = 1][ijd +d = n]\\=\sum_{d\mid n}\sum_{id | (n - d)}[(i, \frac{n - d}{di}) = 1]$
然后就是套路了。
$f(n)=\sum_{d\mid n}\sum_{id | (n - d)}[(i, \frac{n - d}{di}) = 1]\\=\sum_{d|n}\sum_{id|(n-d)}\sum_{e|i \wedge edi\mid (n - d)}\mu(e)\\=\sum_{d|n}\sum_{de|(n - d)}\mu(e)\left( \sum_{e|i\wedge ide\mid(n - d)}1\right )\\=\sum_{d|n}\sum_{e^2d|(n - d)}\mu(e)\sigma_0\left(\frac{n-d}{e^2d}\right)$
设$g(n) = \sum_{e^2|n}\mu(e)\sigma_0(\frac{n}{e^2})$,显然$g(n)$是可以$O(n\log n)$预处理的。考虑$i$在$1, 2,\cdots, n$中作为$\left \lfloor \frac{n}{i} \right \rfloor$个数的因子,然后枚举的总的因子的个数就是一个调和级数的和。对于$f(n)$也可以这样处理。然后就过了。
Code
1 /** 2 * hdu 3 * Problem#5382 4 * Accepted 5 * Time: 655ms 6 * Memory: 33992k 7 */ 8 #include <algorithm> 9 #include <iostream> 10 #include <cstdlib> 11 #include <cstdio> 12 #include <vector> 13 #include <ctime> 14 using namespace std; 15 typedef bool boolean; 16 17 const int N = 1e6 + 1, M = 258280327; 18 19 int add(int a, int b) { 20 a += b; 21 if (a < 0) 22 a += M; 23 if (a >= M) 24 a -= M; 25 return a; 26 } 27 28 int T, n; 29 int f[N], F[N], S[N]; 30 int sl[N], mp[N], mu[N]; 31 int rou[N], g[N]; 32 boolean vis[N]; 33 int num, pri[100000]; 34 35 int tp; 36 int fac[10005]; 37 38 void dfs(int x, int d) { 39 if (x == 1) { 40 fac[tp++] = d; 41 return; 42 } 43 int p = mp[x], link = sl[x]; 44 dfs(sl[x], d); 45 while (!(x % p)) 46 x /= p, d *= p, dfs(link, d); 47 } 48 49 void dfs1(int x, int d) { 50 if (x == 1) { 51 fac[tp++] = d; 52 return; 53 } 54 int p = mp[x], a = 0; 55 while (!(x % p)) 56 x /= p, a++; 57 a = a >> 1; 58 for (int i = 0, pro = 1; i <= a; i++, pro = pro * p) 59 dfs1(x, pro * d); 60 } 61 62 inline void prepare() { 63 mu[1] = 1, rou[1] = 1; 64 for (int i = 2; i < N; i++) { 65 if (!vis[i]) 66 pri[num++] = mp[i] = i, mu[i] = -1, rou[i] = 2, sl[i] = 1; 67 for (int j = 0, x; j < num && pri[j] * i < N; j++) { 68 x = pri[j] * i, vis[x] = true; 69 if (i % pri[j]) 70 mu[x] = -mu[i], mp[x] = pri[j], sl[x] = i, rou[x] = rou[i] << 1; 71 else { 72 mu[x] = 0, mp[x] = pri[j], sl[x] = sl[i], rou[x] = rou[x / pri[j]] + rou[sl[x]]; 73 break; 74 } 75 } 76 } 77 78 g[1] = 1; 79 for (int i = 2; i < N; i++) { 80 tp = 0, dfs1(i, 1); 81 for (int j = 0, x, d; j < tp; j++) { 82 x = fac[j]; 83 d = i / x / x; 84 if (d * x * x == i) 85 g[i] = add(g[i], mu[x] * rou[i / x / x]); 86 } 87 } 88 89 f[1] = 0; 90 int cnt = 0; 91 for (int i = 2; i < N; i++) { 92 tp = 0, dfs(i, 1); 93 cnt += tp; 94 for (int j = 0, x; j < tp; j++) { 95 x = fac[j]; 96 f[i] = add(f[i], g[(i - x) / x]); 97 } 98 } 99 100 F[1] = 1; 101 for (int i = 2; i < N; i++) 102 F[i] = add(add(F[i - 1], -f[i - 1]), 2 * i - 1); 103 S[1] = 1; 104 for (int i = 2; i < N; i++) 105 S[i] = add(S[i - 1], F[i]); 106 } 107 108 inline void solve() { 109 scanf("%d", &n); 110 printf("%d\n", S[n]); 111 } 112 113 int main() { 114 prepare(); 115 scanf("%d", &T); 116 while (T--) 117 solve(); 118 return 0; 119 }