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)\)

推下式子:
\[ \begin{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) g\left(\frac nd\right) = \frac 1k \sum_{d|n} f(d)g'\left(\frac nd\right) \\\Rightarrow \ &f'(n)g(1) + \sum_{d|n, d \neq n} f'(d) g\left(\frac nd\right) = \frac 1k \left[f(n)g'(1) + \sum_{d|n, d\neq n} f(d)g'\left(\frac nd\right)\right]\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], " \n"[i == n]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/cj-xxz/p/12193589.html