Simple Sum 题解

link

题目大意,给一个正整数 \(n\),求 \(\sum_{i=1}^n \frac{n}{gcd(i, n)}\) 的值。

显然题目的答案为 \(\sum_{d|n} d\varphi(d)\),定义为 \(f(n)\)

现在,我们假设 \(n=k\times p^q\),其中 \(p\)\(n\) 的最小质因子。
发现:

\[\sum_{d|n} d\varphi(d)=\sum_{a=0}^q\sum_{d|k} dp^a\varphi(dp^a)=\sum_{a=0}^qp^a\varphi(p^a)\sum_{d|k}d\varphi(d) \]

也就是:

\[f(k\times p^q)=\sum_{a=0}^qp^a\varphi(p^a)\sum_{d|k}d\varphi(d)=f(k)\times f(p^q) \]

进一步得出,对于互质的两个数 \(m,n\)\(f(m)\times f(n)=f(mn)\)。即 \(f\) 为积性函数。

下面我们开始玩板子线性筛推积性函数。

  1. \(i\) 是质数,求 \(f(i)\)

    根据定义,有 \(f_i=1+\varphi(i)i=i(i-1)+1\)

  2. \(p\)\(i\) 的最小质因数,求 \(f(ip)\)

    \(i=xp^k\)​,\(x\)​ 为正整数,\(k\)​ 为正整数且最大。所以有:\(f(ip)=f\left(i/p^k\times p^{k+1}\right)=f\left(i/p^k\right)\times f\left(p^{k+1}\right)\)​。而因为

    \[f\left(p^{k+1}\right)=\sum_{i=0}^{k+1}p^i\varphi(p^i)=\sum_{i=0}^{k}p^i\varphi(p^i)+p^{k+1}\varphi(p^{k+1})=f\left(p^k\right)+p^{k+1}\varphi(p^{k+1}) \]

    所以 \(f(ip)=f\left(i/p^k\times p^{k+1}\right)=f\left(i/p^k\right)\times \left(f\left(p^k\right)+p^{k+1}\varphi(p^{k+1})\right)\)

  3. \(p\) 是质数,与 \(i\) 互质,求 \(f(ip)\)

    \[f(ip)=\sum_{x\mid i}f(x)+f(xp)=\sum_{x\mid i}f(x)+f(p)\times f(x)=\sum_{x\mid i}f(x)\times (1+f(p)) \]

这时就会有聪明的脑板问了:主播主播,怎么知道对于 \(i\) 和与他唯一对应的 \(p\),他的 \(k\) 是多少(指第二种情况)?问得好。其实 \(g(i)\) 也可以线性筛递推。递推如下:

\[g(x)=\left\{\begin{matrix} 1 & x\text{是质数}\\ i & x=ip,p\text{是质数且}\gcd(i,p)=1\\ g(i) & x=ip,p\text{是质数且}\gcd(i,p)\ne1 \end{matrix}\right. \]

一道题,两次线性筛,求三个函数,也是没谁了。时间复杂度 \(O(n+t)\),跑的比 \(O(n+t\log n)\) 慢。

代码:

#include <bits/stdc++.h>
#define FASTIO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
#define int ll
using ll = long long;
using pii = pair<int, int>;
const int N = 1e7 + 5;
int lp[N];
ll sum[N], f[N], phi[N];
int g[N];
vector<int> prime;
void init(void) {
	phi[1] = 1;
	g[1] = 1;
	for (int i = 2; i <= 1e7; ++i) {
		if (lp[i] == 0) {
			lp[i] = i;
			phi[i] = i - 1;
			g[i] = 1;
			prime.push_back(i);
		}
		for (auto x : prime) {
			if (i * x > 1e7) break;
			if (i % x == 0) {
				phi[i * x] = phi[i] * x;
				lp[i * x] = x;
				g[i * x] = g[i];
				break;
			}
			else {
				phi[i * x] = phi[i] * (x - 1);
				lp[i * x] = x;
				g[i * x] = i;
			}
		}
	}
	f[1] = 1;
	for (int i = 2; i <= 1e7; ++i) {
		if (lp[i] == i) 
			f[i] = i * (i - 1) + 1;
		for (auto x : prime) {
			if (i * x > 1e7) break;
			if (i % x == 0) {
				f[i * x] = f[g[i]] * (f[i / g[i]] + phi[i / g[i] * x] * i / g[i] * x);
				break;
			}
			else {
				f[i * x] = f[i] * f[x];
			}
		}
	}
}
signed main() {
	FASTIO;
	init();
	int t; cin >> t;
	while (t --) {
		int n; cin >> n;
		cout << f[n] << '\n';
	}
	return 0;
} 
posted @ 2025-04-09 16:38  tanjiaqi  阅读(40)  评论(0)    收藏  举报