LOJ#6713. 「EC Final 2019」狄利克雷 k 次根 加强版

题面

题解

看到这题第一眼只会 k = 2,百度搜一下「狄利克雷卷积」后得知有一个非常神仙的东西:狄利克雷生成函数。它大概长这样:

[F(z) = sum_{n geq 1} frac {f(n)}{n^z} ]

显然这个函数的卷积对应数论函数 (f) 的狄利克雷卷积。

可以发现 (displaystyle F'(z) = sum_{n geq 1} frac{f(n)ln n}{n^z}),于是记 (f'(n) = f(n) ln n)

于是题目就变成了求函数 (F(x)) 使得 (F(x)^k = G(x))

推下式子:

[egin{aligned}&F^k = G \Rightarrow &kF^{k - 1}F' = G' \Rightarrow &kF'frac{G}{F} = G' \Rightarrow &F'G = frac 1k G'F \Rightarrow &sum_{d|n} f'(d) gleft(frac nd ight) = frac 1k sum_{d|n} f(d)g'left(frac nd ight) \Rightarrow &f'(n)g(1) + sum_{d|n, d eq n} f'(d) gleft(frac nd ight) = frac 1k left[f(n)g'(1) + sum_{d|n, d eq n} f(d)g'left(frac nd ight) ight]end{aligned} ]

由于 (g(1) = 1, g'(1) = 0),所以可以求出 (f'(n)),进而求出 (f(n))

然后这道题就做完了...... 等等,(ln n) 在模意义下是什么东西(

考虑用一些可以替代 (ln n) 的东西。

(f'(n) = c(n) f(n)),若要满足求导的所有性质,就需要使 (c) 满足 (c(nm) = c(n) + c(m))

于是令 (c(n)) 表示 (n) 的质因数个数即可。

代码

#include <cstdio>
#include <algorithm>
#include <vector>

inline int read()
{
	int data = 0, w = 1; char ch = getchar();
	while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
	if (ch == '-') w = -1, ch = getchar();
	while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
	return data * w;
}

const int N(1e6 + 10), Mod(998244353);
int n, K, f[N], g[N], p[N], q[N], v[N];
int prime[N], not_prime[N], cnt, num[N];
int fastpow(int x, int y)
{
	int ans = 1;
	for (; y; y >>= 1, x = 1ll * x * x % Mod)
		if (y & 1) ans = 1ll * ans * x % Mod;
	return ans;
}

void Init()
{
	not_prime[1] = 1, num[1] = 0;
	for (int i = 1; i <= n; i++)
	{
		if (!not_prime[i]) prime[++cnt] = i, num[i] = 1;
		for (int j = 1; j <= cnt && i * prime[j] <= n; j++)
		{
			not_prime[i * prime[j]] = 1, num[i * prime[j]] = num[i] + 1;
			if (!(i % prime[j])) break;
		}
	}
}

int main()
{
	n = read(), K = fastpow(read(), Mod - 2), Init();
	for (int i = 1; i <= n; i++) v[i] = 1ll * (g[i] = read()) * num[i] % Mod;
	for (int i = 1; i <= n; i++)
	{
		int d = (1ll * K * q[i] - p[i] + Mod) % Mod;
		if (i == 1) f[i] = 1, d = 0;
		else f[i] = 1ll * d * fastpow(num[i], Mod - 2) % Mod;
		for (int j = 1; j * i <= n; j++)
			p[j * i] = (p[j * i] + 1ll * d * g[j]) % Mod,
			q[j * i] = (q[j * i] + 1ll * f[i] * v[j]) % Mod;
	}
	for (int i = 1; i <= n; i++)
		printf("%d%c", f[i], " 
"[i == n]);
	return 0;
}
原文地址:https://www.cnblogs.com/cj-xxz/p/12193589.html