Loading

P9308 「DTOI-5」#1f1e33 题解

思路

没有脑子怎么办,使用纯套路解决这道题。

\[\begin{aligned} &=\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^n[i+j+k=n] \operatorname{lcm}(i,\gcd(j,k))\\ &=\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^n[i+j+k=n]\sum_{d=1}^n \operatorname{lcm}(i,d)[\gcd(j,k)=d]&(\text{枚举 gcd})\\ &=\sum_{d=1}^n \sum_{i=1}^n\sum_{j=1}^{\frac{n}{d}}\sum_{k=1}^{\frac{n}{d}}[i+jd+kd=n]\operatorname{lcm}(i,d)[\gcd(j,k)=1]\\ &=\sum_{d=1}^n \sum_{i=1}^n\sum_{j=1}^{\frac{n}{d}}\sum_{k=1}^{\frac{n}{d}}[i+jd+kd=n]\operatorname{lcm}(i,d)\sum_{p|\gcd(j,k)}\mu(p)\\ &=\sum_{d=1}^n \sum_{p=1}^n \mu(p) \sum_{j=1}^{\frac{n}{dp}}\sum_{k=1}^{\frac{n}{dp}}[j+k\le \frac{n}{dp}]\operatorname{lcm}(n-jdp-kdp,d)\\ \end{aligned}\]

\(T=dp\)

\[\begin{aligned} &=\sum_{T=1}^n \sum_{d|T} \sum_{j=1}^{\frac{n}{T}}\sum_{k=1}^{\frac{n}{T}}[j+k\le \frac{n}{T}]\operatorname{lcm}(n-jT-kT,d)\mu(\frac{T}{d})\\ &=\sum_{T=1}^n \sum_{d|T} \sum_{j=1}^{\frac{n}{T}}\sum_{k=1}^{j-1}\operatorname{lcm}(n-jT,d)\mu(\frac{T}{d})&(\text{枚举 j+k 和 j})\\ &=\sum_{T=1}^n \sum_{d|T} \mu(\frac{T}{d}) \sum_{j=1}^{\frac{n}{T}}\operatorname{lcm}(n-jT,d)(j-1)\\ &=\sum_{T=1}^n \sum_{d|T} \mu(\frac{T}{d}) \sum_{j=1}^{\frac{n}{T}}\frac{(n-jT)d(j-1)}{\gcd(n-jT,d)}&(\text{拆开 lcm})\\ \end{aligned}\]

注意到 \(d|T\),所以有 \(\gcd(n-jT,d)=\gcd(n,d)\)

\[\begin{aligned} &=\sum_{T=1}^n \sum_{d|T} \mu(\frac{T}{d}) \sum_{j=1}^{\frac{n}{T}}\frac{(n-jT)d(j-1)}{\gcd(n,d)}\\ &=\sum_{T=1}^n \sum_{d|T} \mu(\frac{T}{d})d \sum_{j=1}^{\frac{n}{T}}\frac{(n-jT)(j-1)}{\gcd(n,d)}\\ &=\sum_{T=1}^n \sum_{d|T} \mu(\frac{T}{d})\frac{d}{\gcd(n,d)} \sum_{j=1}^{\frac{n}{T}}(n-jT)(j-1)\\ \end{aligned}\]

\(S(x)=1+\cdots +x,S2(x)=1^2+\cdots+x^2\)

\[\begin{aligned} &=\sum_{T=1}^n \sum_{d|T} \mu(\frac{T}{d})\frac{d}{\gcd(n,d)} \sum_{j=1}^{\frac{n}{T}}(n-jT)(j-1)\\ &=\sum_{T=1}^n \sum_{d|T} \mu(\frac{T}{d})\frac{d}{\gcd(n,d)} \sum_{j=1}^{\frac{n}{T}}nj-n-j^2T+jT\\ &=\sum_{T=1}^n \sum_{d|T} \mu(\frac{T}{d})\frac{d}{\gcd(n,d)} F(n,T)\\ \end{aligned}\]

其中:

\[\begin{aligned} F(n,T)&=nS(\frac{n}{T})-n(\frac{n}{T})-TS2(\frac{n}{T})+TS(\frac{n}{T}) \end{aligned}\]

这样的式子已经可以获得 \(20\text{pts}\) 的高分了。

\[\begin{aligned} &=\sum_{T=1}^n \sum_{d|T} \mu(\frac{T}{d})\frac{d}{\gcd(n,d)} F(n,T)\\ &=\sum_{p=1}^n\sum_{T=1}^n \sum_{d|T} \mu(\frac{T}{d})\frac{d}{p}[\gcd(n,d)=p] F(n,T)&(\text{传统艺能})\\ &=\sum_{p=1}^n[p|n]\sum_{T=1}^n \sum_{d|T,p|d} \mu(\frac{T}{d})\frac{d}{p}[\gcd(n,d)=1] F(n,T)\\ &=\sum_{p=1}^n[p|n]\sum_{T=1}^n \sum_{d|T,p|d} \mu(\frac{T}{d})\frac{d}{p}\sum_{k|\gcd(n,d)}\mu(k) F(n,T)\\ &=\sum_{p=1}^n\sum_{k=1}^n\mu(k)[pk|n]\sum_{T=1}^n \sum_{d|T,pk|d} \mu(\frac{T}{d})\frac{d}{p}F(n,T)\\ \end{aligned}\]

\(H=pk\)

\[\begin{aligned} &=\sum_{H|n}\sum_{k|H}\mu(k)\sum_{T=1}^n \sum_{d|T,H|d} \mu(\frac{T}{d})\frac{d}{p}F(n,T)\\ &=\sum_{H|n}\sum_{k|H}\mu(k)\sum_{T=1}^{\frac{n}{H}} \sum_{d|T} \mu(\frac{TH}{dH})\frac{dH}{p}F(n,TH)\\ &=\sum_{H|n}\sum_{k|H}\mu(k)\sum_{T=1}^{\frac{n}{H}} \sum_{d|T} \mu(\frac{T}{d})dkF(n,TH)\\ &=\sum_{H|n}\sum_{T=1}^{\frac{n}{H}}F(n,TH)\sum_{k|H}\mu(k) \sum_{d|T} \mu(\frac{T}{d})dk\\ &=\sum_{H|n}\sum_{T=1}^{\frac{n}{H}}F(n,TH)\sum_{k|H}\mu(k)k \sum_{d|T} \mu(\frac{T}{d})d\\ \end{aligned}\]

\(G1(x)=\sum_{d|x}\mu(\frac{x}{d})d=\varphi(x),G2(x)=\sum_{d|x}\mu(x)x\)

\[\begin{aligned} &=\sum_{H|n}\sum_{T=1}^{\frac{n}{H}}F(n,TH)\sum_{k|H}\mu(k)k \sum_{d|T} \mu(\frac{T}{d})d\\ &=\sum_{H|n}\sum_{T=1}^{\frac{n}{H}}F(n,TH)G1(T)G2(H)\\ \end{aligned}\]

这个式子就非常的简洁,可以获得 \(40\text{pts}\) 的高分了。

\[\begin{aligned} &=\sum_{H|n}\sum_{T=1}^{\frac{n}{H}}F(n,TH)G1(T)G2(H)\\ &=\sum_{H|n}G2(H)\sum_{T=1}^{\frac{n}{H}}F(n,TH)G1(T)\\ &=\sum_{H|n}G2(H)\sum_{T=1}^{\frac{n}{H}}((n+TH)S(\frac{n}{TH})-n(\frac{n}{TH})-THS2(\frac{n}{TH}))G1(T)\\ &=\sum_{H|n}G2(H)\sum_{T=1}^{\frac{n}{H}}H((\frac{n}{H}+T)S(\frac{n}{TH})-\frac{n}{H}(\frac{n}{TH})-TS2(\frac{n}{TH}))G1(T)\\ &=\sum_{H|n}G2(H)H\sum_{T=1}^{\frac{n}{H}}((\frac{n}{H}+T)S(\frac{n}{TH})-\frac{n}{H}(\frac{n}{TH})-TS2(\frac{n}{TH}))G1(T)\\ &=\sum_{H|n}G2(H)HG(\frac{n}{H})\\ \end{aligned}\]

其中:

\[\begin{aligned} G(n)=\sum_{T=1}^{n}((n+T)S(\frac{n}{T})-n(\frac{n}{T})-TS2(\frac{n}{T}))G1(T) \end{aligned}\]

只需要计算 \(G(n)\) 即可。

\[\begin{aligned} G(n)&=\sum_{T=1}^{n}((n+T)S(\frac{n}{T})-n(\frac{n}{T})-TS2(\frac{n}{T}))G1(T)\\ &=\sum_{T=1}^{n}-n\varphi(i)(\frac{n}{i})+n\varphi(i)S(\frac{n}{i})+i\varphi(i)S(\frac{n}{i})-i\varphi(i)S2(\frac{n}{i})\\ &=\sum_{T=1}^{n}\frac{(3(\frac{n}{i})^2-3(\frac{n}{i}))n-(2(\frac{n}{i})^3-2(\frac{n}{i}))i}{6}\\ \end{aligned}\]

容易发现,预处理 \(\varphi(i),i\varphi(i)\) 前缀和,可以使用整除分块做到 \(O(n\sqrt n)\)

可以获得 \(60\text{pts}\) 的高分。

但实际上在算 \(1\sim n\) 所有的整除分块的时候,我们有更加优秀的做法。

具体来说。

枚举 \(i\)\(d=n/i\)

那么对应的 \(n\) 要满足 \(id\le n\le i(d+1)-1\)

这样就可以直接用前缀和计算。

至此,所有的东西都可以用最多调和计数的复杂度计算。

时间复杂度:\(O(n\ln n)\)

Code

/*
  ! 如果没有天赋,那就一直重复
  ! Created: 2024/05/24 10:38:16
*/
#include <bits/stdc++.h>
using namespace std;

#define fro(i, x, y) for (int i = (x); i <= (y); i++)
#define pre(i, x, y) for (int i = (x); i >= (y); i--)

const int N = 1e6 + 10;
const int mod = 998244353;

using i64 = long long;

int n, ct;
int vs[N], pr[N], mu[N];
i64 sm[N], fm[N], g1[N], g2[N], p1[N], p2[N], d2[N], d3[N], ans;
vector<int> to[N];

signed main() {
  ios::sync_with_stdio(0), cin.tie(0);
  cin >> n, mu[1] = 1;
  fro(i, 2, n) {
    if (!vs[i]) pr[++ct] = i, mu[i] = -1;
    for (int j = 1; j <= ct && pr[j] * i <= n; j++) {
      vs[i * pr[j]] = 1;
      if (i % pr[j] == 0) {
        mu[i * pr[j]] = 0;
        break;
      }
      mu[i * pr[j]] = -mu[i];
    }
  }
  fro(i, 1, n) {
    for (int j = i, k = 1; j <= n; j += i, k++) {
      g1[j] += i * mu[k];
      g2[j] += i * mu[i];
    }
    g1[i] = (g1[i] % mod + mod) % mod;
    g2[i] = (g2[i] % mod + mod) % mod;
    d2[i] = 1ll * i * i % mod;
    d3[i] = 1ll * i * d2[i] % mod;
  }
  fro(i, 1, n) {
    for (i64 k = 1, l = i, r = 2 * i; l <= n; l += i, r += i, k++) {
      if (r > n) r = n + 1;
      p1[l] += g1[i] * (3 * d2[k] - 3 * k);
      p1[r] -= g1[i] * (3 * d2[k] - 3 * k);
      p2[l] += g1[i] * (2 * d3[k] - 2 * k) * i;
      p2[r] -= g1[i] * (2 * d3[k] - 2 * k) * i;
    }
  }
  fro(i, 1, n) {
    p1[i] = (p1[i] + p1[i - 1]) % mod;
    p2[i] = (p2[i] + p2[i - 1]) % mod;
    sm[i] = (p1[i] * i - p2[i]) % mod;
    sm[i] = (sm[i] % mod + mod) % mod;
    sm[i] = (sm[i] * 166374059) % mod;
  }
  fro(i, 1, n) {
    for (int j = i, k = 1; j <= n; j += i, k++)
      (fm[j] += i * g2[i] % mod * sm[k]) %= mod;
    cout << fm[i] % mod << " \n"[i == n];
  }
  return 0;
}
posted @ 2024-05-24 15:43  JiaY19  阅读(52)  评论(0编辑  收藏  举报