hdu 5382 GCD?LCM! - 莫比乌斯反演

题目传送门

  传送门I

  传送门II

题目大意

  设$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 }
posted @ 2018-09-08 14:55 阿波罗2003 阅读(...) 评论(...) 编辑 收藏