Luogu5349 幂

题面

题解

首先考虑对于一个单项式怎么做,多项式就是单项式的答案的和。

就求一下\(\mathbf f(n) = n^k\)吧。(下面设\(t = \dfrac 1r\)

\(\mathbf S_k = \sum_{n=0}^\infty n^k \left(\dfrac 1t\right)^n\)

\(t\mathbf S_k = \sum_{n=1}^\infty n^k \left(\dfrac 1t\right)^{n-1} = \sum_{n=0}^\infty (n+1)^k \left(\dfrac 1t\right)^n\)

所以\((t - 1) \mathbf S_k = \sum_{n=0}^\infty [(n+1)^k - n^k]\left(\dfrac 1t\right)^n\)

\((n+1)^k\)用二项式定理展开可以发现:

\(\mathbf S_k = \dfrac 1{t-1} \sum_{i=0}^{k-1} \binom ki \mathbf S(i), \mathbf S_0 = \dfrac t{t-1}\)

于是\(\mathbf S_{k} = \dfrac {k!}{t-1}\sum_{i=0}^{k-1} \dfrac 1{(k - i)!} \dfrac {\mathbf S(i)}{i!}\)

显然卷积的形式,分治\(\mathrm{FFT}\)即可。

代码

我不会告诉你我是直接蒯的分治FFT的代码

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define RG register
#define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout);
#define clear(x, y) memset(x, y, sizeof(x))

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

const int Mod(998244353), G(3), maxn(3e5 + 10), phi(Mod - 1);
inline int fastpow(int x, int y)
{
    int ans = 1;
    while(y)
    {
        if(y & 1) ans = 1ll * ans * x % Mod;
        x = 1ll * x * x % Mod, y >>= 1;
    }
    return ans;
}

inline int Inv(int x) { return fastpow(x, Mod - 2); }
int r[maxn], N, m, f[maxn], g[maxn], fac[maxn], inv[maxn], invk;
template<int opt> void FFT(int *p)
{
    for(RG int i = 0; i < N; i++) if(i < r[i]) std::swap(p[i], p[r[i]]);
    for(RG int i = 1; i < N; i <<= 1)
    {
        int rot = fastpow(G, phi / (i << 1));
        for(RG int j = 0; j < N; j += (i << 1))
        {
            int w = 1;
            for(RG int k = 0; k < i; ++k, w = 1ll * w * rot % Mod)
            {
                int x = p[j + k], y = 1ll * w * p[i + j + k] % Mod;
                p[j + k] = (x + y) % Mod, p[i + j + k] = (x - y + Mod) % Mod;
            }
        }
    }
    if(opt == -1) std::reverse(p + 1, p + N);
}

void Div(int l, int r)
{
    static int a[maxn], b[maxn], P;
    if(r - l <= 1) return;
    int mid = (l + r) >> 1;
    Div(l, mid);
    for(m = r - l, N = 1, P = -1; N <= m; N <<= 1, ++P);
    int invn = Inv(N);
    for(RG int i = 0; i < N; i++)
        ::r[i] = (::r[i >> 1] >> 1) | ((i & 1) << P);
    std::copy(f + l, f + mid, a); std::fill(a + mid - l, a + N, 0);
    for(RG int i = 0; i < mid - l; i++) a[i] = 1ll * a[i] * inv[i + l] % Mod;
    std::copy(inv, inv + r - l, b); std::fill(b + r - l, b + N, 0);
    FFT<1>(a), FFT<1>(b);
    for(RG int i = 0; i < N; i++) a[i] = 1ll * a[i] * b[i] % Mod;
    FFT<-1>(a);
    for(RG int i = mid; i < r; i++)
        f[i] = (f[i] + 1ll * fac[i] * a[i - l] % Mod * invk % Mod * invn % Mod) % Mod;
    Div(mid, r);
}

int n, k;
int main()
{
#ifndef ONLINE_JUDGE
    file(cpp);
#endif
    n = read() + 1, k = Inv(read()); invk = Inv(k - 1); fac[0] = inv[0] = 1;
    for(RG int i = 1; i <= n + n; i++) fac[i] = 1ll * fac[i - 1] * i % Mod;
    inv[n + n] = Inv(fac[n + n]);
    for(RG int i = n + n - 1; i; i--) inv[i] = 1ll * inv[i + 1] * (i + 1) % Mod;
    f[0] = 1ll * k * invk % Mod; Div(0, n);
    int ans = 0;
    for(RG int i = 0; i < n; i++)
        ans = (ans + 1ll * read() * f[i] % Mod) % Mod;
    printf("%d\n", ans);
    return 0;
}

转载于:https://www.cnblogs.com/cj-xxz/p/10812424.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值