51nod 1172 Partial Sums V2

Posted mrzdtz220

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 1172 Partial Sums V2相关的知识,希望对你有一定的参考价值。

 


看了讨论区一个回答恍然大悟,%%%

幂级数 $F(x)=A(x)^p$,那么有 $F^{‘}(x)=pA^{‘}(x)A(x)^{p-1}$,$A(x)F^{‘}(x)=pF(x)A^{‘}(x)$。
若 $a_0,a_1,dots$ 的普通生成函数为 $A(x)$,令 $s_n=sum limits_{i=0}^n a_i$,那么 $s_0,s_1,dots$ 的普通生成函数为 $A(x)/(1-x)$,相当于与多项式 $B(x)=1 + x + x^2dots$ 进行一次卷积。即对一个数列进行求一次前缀和,就相当于其生成函数乘上 $dfrac{1}{1-x}$,进行 $k$ 次前缀和就相当于乘上 $dfrac{1}{(1-x)^k}$。
先求 $B(x)=dfrac{1}{(1-x)^k}$ 的每一项。

$B(x)=(1-x)^{-k}$
$(1-x)B^{‘}(x)=-1 imes B(x) imes (-k)=kB(x)$
$sumlimits_{n=0}^{infty}(n+1)b_{n+1}x^n - sum limits_{n=1}^{infty}nb_nx^n=sumlimits_{n=0}^{infty}kb_nx_n$
$b_0=B(0)=1$
$b_1=kb_0=k$
$(n+1)b_{n+1}-nb_n=kb_n Leftrightarrow b_{n+1}=dfrac{(n+k)b_n}{n+1}$
可以 $O(n)$ 得到 $b$ 序列,再和 $a$ 进行一次卷积。
模数是$10^9+7$,可以用一个叫 ’拆系数FFT‘的东西解决,只需要4次DFT,先当模板用着。。。

技术图片
#include <bits/stdc++.h>
using ll = long long;
using db = long double;

const int N = 2e5 + 7;
const int MOD = 1e9 + 7;

#define upmo(a, b) (((a) = ((a) + (b)) % MOD) < 0 ? (a) += MOD : (a))

namespace FFT_MO {
    const int FFT_MAXN = 1 << 18;
    const db PI = 4 * atan(1.0);
    struct Complex {
        db r, i;
        Complex(){}
        Complex(db r, db i): r(r), i(i) {}
        Complex operator + (const Complex &p) const { return Complex(r + p.r, i + p.i); }
        Complex operator - (const Complex &p) const { return Complex(r - p.r, i - p.i); }
        Complex operator * (const Complex &p) const { return Complex(r * p.r - i * p.i, r * p.i + i * p.r); }
        Complex operator !() const { return Complex(r, -i); }
    } nw[FFT_MAXN + 1], f[FFT_MAXN], g[FFT_MAXN], t[FFT_MAXN];
    int bitrev[FFT_MAXN];
    void init() {
        int L = 0; while ((1 << L) != FFT_MAXN) L++;
        for (int i = 1; i < FFT_MAXN; i++)
            bitrev[i] = bitrev[i >> 1] >> 1 | ((i & 1) << (L - 1));
        for (int i = 0; i <= FFT_MAXN; i++)
            nw[i] = Complex((db)cosl(2 * PI / FFT_MAXN * i), (db)sinl(2 * PI / FFT_MAXN * i));
    }
    void dft(Complex *a, int n, int flag = 1) {
        int d = 0; while ((1 << d) * n != FFT_MAXN) d++;
        for (int i = 0; i < n; i++) if (i < (bitrev[i] >> d))
                std::swap(a[i], a[bitrev[i] >> d]);
        for (int l = 2; l <= n; l <<= 1) {
            int del = FFT_MAXN / l * flag;
            for (int i = 0; i < n; i += l) {
                Complex *le = a + i, *ri = a + i + (l >> 1);
                Complex *w = flag == 1 ? nw : nw + FFT_MAXN;
                for (int k = 0; k < (l >> 1); k++) {
                    Complex ne = *ri * *w;
                    *ri = *le - ne, *le = *le + ne;
                    le++, ri++, w += del;
                }
            }
        }
        if (flag != 1) for (int i = 0; i < n; i++) a[i].r /= n, a[i].i /= n;
    }
    void convo(ll *a, int n, ll *b, int m, ll *c) {
        for (int i = 0; i <= n + m; i++) c[i] = 0;
        int N = 2; while (N <= n + m) N <<= 1;
        for (int i = 0; i < N; i++) {
            ll aa = i <= n ? a[i] : 0, bb = i <= m ? b[i] : 0;
            aa %= MOD, bb %= MOD;
            f[i] = Complex(db(aa >> 15), db(aa & 32767));
            g[i] = Complex(db(bb >> 15), db(bb & 32767));
        }
        dft(f, N), dft(g, N);
        for (int i = 0; i < N; i++) {
            int j = i ? N - i : 0;
            t[i] = ((f[i] + !f[j]) * (!g[j] - g[i]) + (!f[j] - f[i]) * (g[i] + !g[j])) * Complex(0, 0.25);
        }
        dft(t, N, -1);
        for (int i = 0; i <= n + m; i++) upmo(c[i], (ll(t[i].r + 0.5)) % MOD << 15);
        for (int i = 0; i < N; i++) {
            int j = i ? N - i : 0;
            t[i] = (!f[j] - f[i]) * (!g[j] - g[i]) * Complex(-0.25, 0) + Complex(0, 0.25) * (f[i] + !f[j]) * (g[i] + !g[j]);
        }
        dft(t, N, -1);
        for (int i = 0; i <= n + m; i++)
            upmo(c[i], ll(t[i].r + 0.5) + (ll(t[i].i + 0.5) % MOD << 30));
    }
}

ll a[N], b[N], inv[N], ans[N];

void M(int &a) {
    if (a >= MOD) a -= MOD;
    if (a < 0) a += MOD;
}

int main() {
    freopen("ans.out", "w", stdout);
    int n, k;
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++) 
        scanf("%lld", a + i);
    FFT_MO::init();
    inv[1] = 1;
    for (int i = 2; i <= n; i++)
        inv[i] = (1LL * (MOD - MOD / i) * inv[MOD % i]) % MOD;
    b[0] = 1; b[1] = k;
    for (int i = 1; i <= n; i++)
        b[i] = 1LL * b[i - 1] * (i + k - 1) % MOD * inv[i] % MOD;
    FFT_MO::convo(a, n + 1, b, n + 1, ans);
    /*for (int i = 1; i <= n; i++) {
        int ans = 0;
        for (int j = 0; j <= i; j++)
            M(ans += 1LL * a[i - j] * b[j] % MOD);
        printf("%d
", ans);
    }*/
    for (int i = 1; i <= n; i++)
        printf("%lld
", ans[i]);
    return 0;
}
View Code

 

以上是关于51nod 1172 Partial Sums V2的主要内容,如果未能解决你的问题,请参考以下文章

51nod 1172 Partial Sums V2

51nod 1172 Partial Sums V2 卡精度的任意模数FFT

51nod1161 Partial Sums

51nod 1161 Partial Sums

题解 [51nod1161] Partial Sums

Non-negative Partial Sums(单调队列)