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; }
以上是关于51nod 1172 Partial Sums V2的主要内容,如果未能解决你的问题,请参考以下文章