题目
题目链接:https://www.luogu.com.cn/problem/P5488
给定一个长为 (n) 的序列 (a),求出其 (k) 阶差分或前缀和。
结果的每一项都需要对 (1004535809) 取模。
(nleq 10^5,1le k le 10^{2333}, k
ot equiv 0 pmod{1004535809})
思路
我们把 (a_i) 看做一个多项式的第 (i) 项系数。也就是
[F(x)=sum^{n}_{i=1}a_ix^i
]
前缀和和差分分开来做。
Part 1.前缀和
我们要求它的前缀和。也就是给上式乘上 ((1+x+x^2+x^3+cdots x^n)^k)。
由于 (1+x+x^2+x^3+cdots x^n=frac{1}{1-x}),所以我们所求就是 (F imes frac{1}{(1-x)^k})。
[frac{1}{(1-x)^k}=sum^{+infty}_{i=0}(-1)^ifrac{(-1)^i·(k+1-i)^underline{i}}{i!}x^i=sum^{+infty}_{i=0}frac{(k-i+1)^underline{i}}{i!}x^i
]
由于
[frac{(k-i+1)^underline{i}}{i!}=egin{pmatrix}k+i-1\iend{pmatrix}
]
所以
[frac{1}{(1-x)^k}=sum^{+infty}_{i=0}egin{pmatrix}k+i-1\iend{pmatrix}x^i
]
组合数递推,然后就是卷积的形式了。上 NTT 即可。
Part 2.差分
同理,等价于求 (F imes (1-x)^k)。
由二项式定理得
[(1-x)^k=sum^{+infty}_{i=0}1^{k-i}(-1)^{i}x^iegin{pmatrix}k\iend{pmatrix}=sum^{+infty}_{i=0}(-1)^{i}egin{pmatrix}k\iend{pmatrix}x^i
]
照样可以递推做。然后也是 NTT。
时间复杂度 (O(nlog n))。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=300010,MOD=1004535809,G=3,Ginv=334845270;
int n,m,type,len,lim,rev[N];
ll f[N],g[N];
char s[N];
ll fpow(ll x,ll k)
{
ll ans=1;
for (;k;k>>=1,x=x*x%MOD)
if (k&1) ans=ans*x%MOD;
return ans;
}
void NTT(ll *f,int tag)
{
for (int i=0;i<lim;i++)
if (i<rev[i]) swap(f[i],f[rev[i]]);
for (int k=1;k<lim;k<<=1)
{
ll tmp=fpow((tag==1)?G:Ginv,(MOD-1)/(k<<1));
for (int i=0;i<lim;i+=(k<<1))
{
ll w=1;
for (int j=0;j<k;j++,w=w*tmp%MOD)
{
ll x=f[i+j],y=w*f[i+j+k]%MOD;
f[i+j]=(x+y)%MOD; f[i+j+k]=(x-y)%MOD;
}
}
}
}
int main()
{
scanf("%d%s%d",&n,s,&type);
len=strlen(s);
for (int i=0;i<len;i++) m=(10LL*m+s[i]-48)%MOD;
for (int i=1;i<=n;i++) scanf("%lld",&f[i]);
lim=1;
while (lim<=2*n) lim<<=1;
for (int i=0;i<lim;i++)
rev[i]=(rev[i>>1]>>1)|((i&1)?(lim>>1):0);
g[1]=1;
if (!type)
{
for (int i=1;i<n;i++)
g[i+1]=g[i]*(m+i-1)%MOD*fpow(i,MOD-2)%MOD;
}
else
{
for (int i=1;i<n;i++)
g[i+1]=-g[i]*(m-i+1)%MOD*fpow(i,MOD-2)%MOD;
}
NTT(f,1); NTT(g,1);
for (int i=0;i<lim;i++) f[i]=f[i]*g[i]%MOD;
NTT(f,-1);
ll inv=fpow(lim,MOD-2);
for (int i=2;i<=n+1;i++)
printf("%lld ",(f[i]*inv%MOD+MOD)%MOD);
return 0;
}