P5488 差分与前缀和
先看前缀和。
首先有一个显然的递推:
\[sum_{k,i}=sum_{k,i-1}+sum_{k-1,i}\\
sum_{0,i}=a_i
\]
按照套路考虑 \(a_j\) 对 \(sum_{k,i}\) 的贡献。
看看这个递推,不就是从 \((0,j)\) 走到 \((k,i)\) 这个点的方案数吗??直接 \(\binom{k+i-j}{k}\) 即可。
然后发现挂掉了。。。。。。。
忽然发现 \(sum_{0,i}\) 不能转移到 \(sum_{0,i+1}\) 的!于是少了一步,应该是 \(\binom{k-1+i-j}{k-1}\) !
注意这个 \(k\) 太大了,但是是可以直接 \(\bmod 998244353\) 的。然后递推 \(p_i=\binom{k+i}{k}\) 即可。
发现 \(a*p\) 就是答案了。
再考虑差分。
之前见过一点生成函数内容。 \(k\) 阶差分就是乘上 \((1-x)^k\) ,这东西二项式系数就是 \((-1)^i\binom{k}{i}\)
递推预处理 \(p_i=(-1)^i\binom{k}{i}\) ,\(a*p\) 就是答案了。
const int N=100005;
const int M=N<<2;
#define mod 1004535809
void fmod(int&x){x+=x>>31&mod,x-=mod,x+=x>>31&mod;}
int qpow(int n,int k){int res=1;for(;k;k>>=1,n=1ll*n*n%mod)if(k&1)res=1ll*n*res%mod;return res;}
inline int exread(){
int x=0;char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))x=(1ll*x*10+ch-'0')%mod,ch=getchar();
return x;
}
int rev[M],lg,lim;
void init(const int&n){
for(lg=0,lim=1;lim<=n;lim<<=1,++lg);
for(int i=0;i<lim;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg-1));
}
void NTT(int*a,int op){
int g=op?3:qpow(3,mod-2);
for(int i=0;i<lim;++i)if(i>rev[i])swap(a[i],a[rev[i]]);
for(int i=1;i<lim;i<<=1){
int wn=qpow(g,(mod-1)/(i<<1));
for(int j=0;j<lim;j+=i<<1){
int w0=1;
for(int k=0;k<i;++k,w0=1ll*w0*wn%mod){
const int X=a[j+k],Y=1ll*w0*a[i+j+k]%mod;
fmod(a[j+k]=X+Y),fmod(a[i+j+k]=X-Y+mod);
}
}
}
if(op)return;int ilim=qpow(lim,mod-2);
for(int i=0;i<lim;++i)a[i]=1ll*ilim*a[i]%mod;
}
int n,k,t,a[M],f[M];
namespace solve1{
signed main(){
f[0]=1;for(int i=1;i<n;++i)f[i]=1ll*f[i-1]*(k+i-1)%mod*qpow(i,mod-2)%mod;
init(n<<1),NTT(a,1),NTT(f,1);
for(int i=0;i<lim;++i)f[i]=1ll*a[i]*f[i]%mod;
NTT(f,0);
for(int i=0;i<n;++i)fmod(f[i]),printf("%d ",f[i]);
return 0;
}
}
namespace solve2{
signed main(){
f[0]=1;for(int i=1;i<n;++i)f[i]=-1ll*f[i-1]*(k-i+1)%mod*qpow(i,mod-2)%mod;
init(n<<1),NTT(a,1),NTT(f,1);
for(int i=0;i<lim;++i)f[i]=1ll*a[i]*f[i]%mod;
NTT(f,0);
for(int i=0;i<n;++i)fmod(f[i]),printf("%d ",f[i]);
return 0;
}
}
signed main(){
n=read(),k=exread(),t=read();
for(int i=0;i<n;++i)a[i]=read();
if(!t)solve1::main();else solve2::main();
return 0;
}
大概是我人傻常数大的缘故,不知道为啥别人跑的这么快。。。
路漫漫其修远兮,吾将上下而求索