GMOJ5516. Function

2021/10/4 6:13:22

本文主要是介绍GMOJ5516. Function,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

题目大意

\[\sum_{i=1}^n\sum_{d|i}\mu(d)\sigma_0^2(\frac i d) \]

\(n\le 10^9, T \le 10\)。

解题思路

讲题的时候讲的可能不太清晰。这里给出一个详细的过程。

许多人都发现了这道题是一个min_25筛的版题并爆切了,但是否有人尝试证明了呢?

根据SDOI2015 约数个数和,我们得到 \(\sigma_0(ij)=\sum\limits_{x|i}\sum\limits_{y|i}[\gcd(x,y)=1]\) 。

受此启发,加上式子中有 \(\mu\) 函数,我们可以考虑反推出反演过程,即(从下往上看):

\(\begin{aligned} \sum_{i=1}^n\sigma_0(i^2) &= \sum\limits_{i=1}^n\sum_{x|i}\sum_{y|i}[\gcd(x,y)=1] \\ &= \sum\limits_{i=1}^n\sum_{x|i}\sum_{y|i}\sum_{d|\gcd(x,y)}\mu(d) \\ &= \sum_{i=1}^n\sum_{d|i}\mu(d)\sum_{d|x,x|i}\sum_{d|y,y|i}1 \\ &= \sum_{i=1}^n\sum_{d|i}\mu(d)\sigma_0^2(\frac i d)\end{aligned}\)

显然 \(f(x)=d(x^2)\) 是一个积性函数,并且有\(f(p^c)=2c+1\),这与大家打表出来的结果一致。

最后本人猜测出题人也是这么想到的。

代码

#include <cmath>
#include <cstdio>
#include <algorithm>
#define fo(i, a, b) for(int i = (a); i <= (b); ++i)
#define ll long long
using namespace std;
const int N = 32e4;
bool v[N + 10];
int tot;
ll p[N + 10], n, sq, m, w[N + 10], sum[N + 10], g[N + 10], id1[N + 10], id2[N + 10];
void pre() {
	fo(i, 2, N)  {
		if(!v[i]) ++tot, p[tot] = i;
		for(int j = 1; p[j] * i <= N && j <= tot; ++j) {
			v[i * p[j]] = 1;
			if(!(i % p[j])) break;
		}
	}
	fo(i, 1, tot)	sum[i] = i * 3;
}
ll getid(ll x) { return x <= sq ? id1[x] : id2[n / x];}
ll S(ll x, int j) {
	if(p[j] > x) return 0;
	ll Ans = g[getid(x)] - sum[j];
	for(int i = j + 1; i <= tot && p[i] * p[i] <= x; ++i)
		for(ll e = 1, sp = p[i]; sp <= x; sp *= p[i], ++e)
			Ans += (e * 2 + 1) * (S(x / sp, i) + (e > 1));
	return Ans;
}
int main() {
	freopen("function.in", "r", stdin);
	freopen("function.out", "w", stdout);
	pre();
	int T;
	for(scanf("%d", &T); T; --T) {
		scanf("%lld", &n), sq = sqrt(n), m = 0;
		for(ll l = 1, r; l <= n; l = r + 1) {
			r = (n / (n / l)), w[++m] = n / l;
			g[m] = 3 * (w[m] - 1);
			w[m] <= sq ? id1[w[m]] = m : id2[n / w[m]] = m;
		}
		fo(i, 1, tot)
			for(int j = 1; j <= m && p[i] * p[i] <= w[j]; ++j)
				g[j] -= (g[getid(w[j] / p[i])] - sum[i - 1]);
		printf("%lld\n", S(n, 0) + 1);
	}
	return 0;
}


这篇关于GMOJ5516. Function的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程