题目链接
设数组 A = { a 0 , a 1 , . . . , a ∞ } A=\{a_0,a_1,...,a_{\infty}\} A={a0,a1,...,a∞},数组 B = { b 0 , b 1 , . . . , b ∞ } = { 1 , 1 , 1 , . . } B=\{b_0,b_1,...,b_{\infty}\}=\{1,1,1,..\} B={b0,b1,...,b∞}={1,1,1,..},一阶前缀和数组为: S = { s 0 , s 1 , . . . , s ∞ } S=\{s_0,s_1,...,s_{\infty}\} S={s0,s1,...,s∞}, s i = ∑ j = 0 i a j s_i=\sum_{j=0}^{i}a_j si=∑j=0iaj。
S S S可以看成 A A A和 B B B的卷积: s i = ∑ j + k = i , j ≥ 0 , k ≥ 0 a j × b k s_i=\sum_{j+k=i,j\ge0,k\ge0}a_j\times b_k si=∑j+k=i,j≥0,k≥0aj×bk。
s 0 = a 0 × b 0 = a 0 s_0=a_0\times b_0=a_0 s0=a0×b0=a0 |
---|
s 1 = a 0 × b 1 + a 1 × b 0 = a 0 + a 1 s_1=a_0\times b_1+a_1\times b_0=a_0+a_1 s1=a0×b1+a1×b0=a0+a1 |
s 2 = a 0 × b 2 + a 1 × b 1 + a 2 × b 0 = a 0 + a 1 + a 2 s_2=a_0\times b_2+a_1\times b_1+a_2\times b_0=a_0+a_1+a_2 s2=a0×b2+a1×b1+a2×b0=a0+a1+a2 |
… |
A = a 0 + a 1 x + a 2 x 2 + . . . + a ∞ x ∞ A=a_0+a_1x+a_2x^2+...+a_{\infty}x^{\infty} A=a0+a1x+a2x2+...+a∞x∞, B = 1 + x + x 2 + . . . + x ∞ B=1+x+x^2+...+x^{\infty} B=1+x+x2+...+x∞, S = A × B S=A\times B S=A×B。
可以发现 B B B是一个公比为 x x x的等比数列,根据等比数列求和公式: a 1 × ( 1 − q n ) 1 − q = 1 − x ∞ 1 − x \frac{a_1\times(1-q^n)}{1-q}=\frac{1-x^{\infty}}{1-x} 1−qa1×(1−qn)=1−x1−x∞,取 x < 1 x<1 x<1,则 B = 1 1 − x B=\frac{1}{1-x} B=1−x1。
因为卷积操作满足结合律,则 K K K阶前缀和可以看做 S = A × ( 1 1 − x ) k S=A\times (\frac{1}{1-x})^k S=A×(1−x1)k。
需要注意,在广义二项式定理中, k = 0 k=0 k=0时 C α k = 1 C_{\alpha}^k=1 Cαk=1。
广义牛顿二项式展开? - andrew shen的回答 - 知乎
对 B = ( 1 1 − x ) k = ( 1 − x ) − k B=(\frac{1}{1-x})^k=(1-x)^{-k} B=(1−x1)k=(1−x)−k进行分析,根据扩展二项式定理,可以将 B B B拆成:
( 1 − x ) − k = ∑ i = 0 ∞ ( − k ) ( − k − 1 ) ( − k − 2 ) . . . ( − k − i + 1 ) i ! × 1 k − i × ( − x ) i = ∑ i = 0 ∞ ( − k ) ( − k − 1 ) ( − k − 2 ) . . . ( − k − i + 1 ) i ! × ( − 1 ) i × x i = ∑ i = 0 ∞ ( − k ) ( − k − 1 ) ( − k − 2 ) . . . ( − k − i + 1 ) i ! × ( − 1 ) i × x i = ∑ i = 0 ∞ ( k ) ( k + 1 ) ( k + 2 ) . . . ( k + i − 1 ) i ! × ( − 1 ) 2 i × x i = ∑ i = 0 ∞ ( k ) ( k + 1 ) ( k + 2 ) . . . ( k + i − 1 ) i ! × x i = ∑ i = 0 ∞ C k + i − 1 i × x i \begin{matrix} (1-x)^{-k} &=& \sum_{i=0}^{\infty}\frac{(-k)(-k-1)(-k-2)...(-k-i+1)}{i!}\times 1^{k-i}\times (-x)^{i} \\ &=& \sum_{i=0}^{\infty}\frac{(-k)(-k-1)(-k-2)...(-k-i+1)}{i!}\times (-1)^i\times x^{i} \\ &=& \sum_{i=0}^{\infty}\frac{(-k)(-k-1)(-k-2)...(-k-i+1)}{i!}\times (-1)^i\times x^{i} \\ &=& \sum_{i=0}^{\infty}\frac{(k)(k+1)(k+2)...(k+i-1)}{i!}\times (-1)^{2i}\times x^{i} \\ &=& \sum_{i=0}^{\infty}\frac{(k)(k+1)(k+2)...(k+i-1)}{i!}\times x^{i} \\ &=& \sum_{i=0}^{\infty}C_{k+i-1}^i\times x^{i} \end{matrix} (1−x)−k======∑i=0∞i!(−k)(−k−1)(−k−2)...(−k−i+1)×1k−i×(−x)i∑i=0∞i!(−k)(−k−1)(−k−2)...(−k−i+1)×(−1)i×xi∑i=0∞i!(−k)(−k−1)(−k−2)...(−k−i+1)×(−1)i×xi∑i=0∞i!(k)(k+1)(k+2)...(k+i−1)×(−1)2i×xi∑i=0∞i!(k)(k+1)(k+2)...(k+i−1)×xi∑i=0∞Ck+i−1i×xi
只需要将 A A A与 B = ∑ i = 0 ∞ C k + i − 1 i × x i B=\sum_{i=0}^{\infty}C_{k+i-1}^i\times x^{i} B=∑i=0∞Ck+i−1i×xi卷积即可。【可以递推计算】
设数组 A = { a 0 , a 1 , . . . , a ∞ } A=\{a_0,a_1,...,a_{\infty}\} A={a0,a1,...,a∞},数组 B = { b 0 , b 1 , . . . , b ∞ } = { 1 , − 1 , 0 , 0 , . . } B=\{b_0,b_1,...,b_{\infty}\}=\{1,-1,0,0,..\} B={b0,b1,...,b∞}={1,−1,0,0,..},一阶前缀和数组为: S = { s 0 , s 1 , . . . , s ∞ } S=\{s_0,s_1,...,s_{\infty}\} S={s0,s1,...,s∞}, s i = ∑ j = 0 i a j s_i=\sum_{j=0}^{i}a_j si=∑j=0iaj。
S S S可以看成 A A A和 B B B的卷积: s i = ∑ j + k = i , j ≥ 0 , k ≥ 0 a j × b k s_i=\sum_{j+k=i,j\ge0,k\ge0}a_j\times b_k si=∑j+k=i,j≥0,k≥0aj×bk。
s 0 = a 0 × b 0 = a 0 s_0=a_0\times b_0=a_0 s0=a0×b0=a0 |
---|
s 1 = a 0 × b 1 + a 1 × b 0 = a 1 − a 0 s_1=a_0\times b_1+a_1\times b_0=a_1-a_0 s1=a0×b1+a1×b0=a1−a0 |
s 2 = a 0 × b 2 + a 1 × b 1 + a 2 × b 0 = a 2 − a 1 s_2=a_0\times b_2+a_1\times b_1+a_2\times b_0=a_2-a_1 s2=a0×b2+a1×b1+a2×b0=a2−a1 |
… |
A = a 0 + a 1 x + a 2 x 2 + . . . + a ∞ x ∞ A=a_0+a_1x+a_2x^2+...+a_{\infty}x^{\infty} A=a0+a1x+a2x2+...+a∞x∞, B = 1 − x B=1-x B=1−x, S = A × B S=A\times B S=A×B。
因为卷积操作满足结合律,则 K K K阶差分可以看做 S = A × ( 1 − x ) k S=A\times (1-x)^k S=A×(1−x)k。
根据二项式定理,可以将 B B B拆成: ( 1 − x ) k = ∑ i = 0 ∞ C k i × ( − x ) i = ∑ i = 0 ∞ C k i × ( − 1 ) i × x i (1-x)^k=\sum_{i=0}^{\infty}C_k^i\times (-x)^i=\sum_{i=0}^{\infty}C_k^i\times (-1)^i \times x^i (1−x)k=∑i=0∞Cki×(−x)i=∑i=0∞Cki×(−1)i×xi。
只需要将 A A A与 B = ∑ i = 0 ∞ C k i × ( − 1 ) i × x i B=\sum_{i=0}^{\infty}C_k^i\times (-1)^i \times x^i B=∑i=0∞Cki×(−1)i×xi卷积即可。【可以递推计算】
#include
using namespace std;
#define ll long long
#define int long long
const int mod = 1004535809;
const int N = 1e5 + 5;
int n, k, A[N << 2], B[N << 2], limit, L, Inv, R[N << 2];
int readMod() { // 读取,防止溢出
char cc = getchar();
int cn = 0, flus = 1;
while (cc < '0' || cc > '9') {
if (cc == '-') flus = -flus;
cc = getchar();
}
while (cc >= '0' && cc <= '9')
cn = (cn * 10 + cc - '0') % mod, cc = getchar();
return cn * flus;
}
ll power(ll a, ll b) {
ll res = 1;
while (b) {
if (b & 1) res = (res * a) % mod;
a = (a * a) % mod, b >>= 1;
}
return res;
}
ll inv(ll x) { return power(x, mod - 2); }
void init(int x) {
limit = 1, L = 0;
while (limit <= x) limit <<= 1, ++L;
for (int i = 0; i <= limit; i++)
R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1));
Inv = power(limit, mod - 2);
}
void NTT(int *a, int type) {
int Gi = inv(3), G = 3;
for (int i = 0; i < limit; ++i)
if (R[i] > i) swap(a[i], a[R[i]]);
for (int k = 1; k < limit; k <<= 1) {
int d = power((type == 1) ? G : Gi, (mod - 1) / (k << 1));
for (int i = 0; i < limit; i += (k << 1))
for (int j = i, g = 1; j < i + k; ++j, g = (g * d) % mod) {
int Nx = a[j], Ny = (a[j + k] * g) % mod;
a[j] = (Nx + Ny) % mod, a[j + k] = (Nx - Ny + mod) % mod;
}
}
if (type != 1)
for (int i = 0; i <= limit; i++) a[i] = a[i] * Inv % mod;
}
signed main() {
int type;
cin >> n;
k = readMod();
cin >> type;
for (int i = 0; i < n; i++) cin >> A[i];
B[0] = 1;
if (type == 0) // 前缀和
for (int i = 1; i <= n; i++)
B[i] = B[i - 1] * (k + i - 1) % mod * inv(i) % mod;
if (type == 1) // 差分
for (int i = 1; i <= n; i++)
B[i] = (-B[i - 1] * (k - i + 1 + mod) % mod * inv(i) % mod + mod) %
mod;
// ============================================================NTT
init(n + n), NTT(A, 1), NTT(B, 1);
for (int i = 0; i <= limit; i++) A[i] = A[i] * B[i] % mod;
NTT(A, -1);
// ============================================================
for (int i = 0; i < n; i++) cout << A[i] << " ";
return 0;
}