差分与前缀和
\(\text{Solution}\)
对于求前缀和,相当于把\(a\)数列的生成函数乘以\((1,1,1,...)\)的生成函数。
即乘以\(\frac{1}{1 - x}\),\(k\)阶即乘以\(\frac{1}{(1-x)^k}\)。
将其展开就为
\[\sum_{i \ge 0} \binom{i + k - 1}{k - 1}x^i = \sum_{i \ge 0} \frac{k^{\overline{i}}}{i!}x^i
\]
对于求差分就简单了
相当于乘以\((1 - x)^k\)
展开为
\[\sum_{i = 0}^k (-1)^i\frac{k^{\underline{i}}}{i!}x^i
\]
最后套上\(NTT\)即可。
\(\text{Code}\)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#define LL long long
#define RE register
#define IN inline
using namespace std;
const int N = 1e5,P = 1004535809;
LL a[N << 2],f[N << 2]; int n,t,rev[N << 2],k;
inline LL read() {
LL res = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar());
for (; isdigit(ch); ch = getchar()) res = (res * 10LL % P + (ch ^ 48)) % P;
return res;
}
LL fpow(LL x,LL y)
{
LL res = 1;
for (; x; x >>= 1,y = y * y % P)
if (x & 1) res = res * y % P;
return res;
}
void NTT(LL *a,int len,int fl)
{
if (len == 1) return;
for (int i = 1; i < len; i++)
if (i < rev[i]) swap(a[i],a[rev[i]]);
for (int l = 1; l < len; l <<= 1)
{
LL I = fpow((P - 1) / (l << 1),3LL);
if (fl == -1) I = fpow(P - 2,I);
for (int i = 0; i < len; i += (l << 1))
{
LL W = 1;
for (int j = 0; j < l; j++,W = W * I % P)
{
LL x = a[i + j],y = W * a[i + j + l] % P;
a[i + j] = (x + y) % P,a[i + j + l] = (x - y + P) % P;
}
}
}
}
int main()
{
n = read() - 1, k = read(), t = read();
for (int i = 0; i <= n; i++) a[i] = read();
if (t) {
f[0] = 1; LL tmp = 1;
for (LL i = 1,fl = -1LL; i <= min(n,k); i++,fl *= -1LL)
tmp = tmp * (LL)(k - i + 1LL) % P * fpow(P - 2,i) % P,f[i] = (fl * tmp + P) % P;
}
else {
f[0] = 1; LL tmp = 1;
for (LL i = 1; i <= n; i++)
tmp = tmp * (LL)(k + i - 1LL) % P * fpow(P - 2,i) % P,f[i] = tmp;
}
int len = 1,bit = 0;
while (len <= n << 1) len <<= 1,bit++;
for (int i = 1; i < len; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << bit - 1);
NTT(a,len,1),NTT(f,len,1);
for (int i = 0; i < len; i++) a[i] = a[i] * f[i] % P;
NTT(a,len,-1); LL inv = fpow(P - 2,len);
for (int i = 0; i <= n; i++) printf("%lld ",a[i] * inv % P);
}