题目
题目描述
给定一个长为 nn 的序列 aa,求出其 kk 阶差分或前缀和。
结果的每一项都需要对 10045358091004535809 取模。
输入格式
第一行三个整数 n,k,tn,k,t,若 t=0t=0 表示求前缀和,t=1t=1 表示求差分。
第二行 nn 个整数,表示序列 aa。
输出格式
输出一行 nn 个整数,表示 aa 的 kk 阶差分或前缀和。
输入输出样例
输入 #1复制
8 3 0
1 9 2 6 0 8 1 7
输出 #1复制
1 12 35 76 135 220 332 478
输入 #2复制
8 3 1
1 9 2 6 0 8 1 7
输出 #2复制
1 6 1004535787 26 1004535788 24 1004535780 28
说明/提示
【数据范围】
1 \le n \le 10^51≤n≤10
5
0 \le a_i \le 10^90≤a
i
≤10
9
1\le k \le 10^{2333}, k \not \equiv 0 \pmod{1004535809}1≤k≤10
2333
,k
≡0(mod1004535809)
思路
发现做一次前缀和就相当于与 1 1 1 做一次卷积, k k k 阶前缀和相当于做 k k k 此卷积。由于卷积有结合律,所以我们相当于要卷上 1 ( 1 − x ) k \frac{1}{(1-x)^k} (1−x)k1,多项式求逆即可
差分就是这东西的倒数啦
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=333333,mod=1004535809;
int n,tp,k,a[N],lim,l,rev[N],b[N],fac[N],invfac[N];
int add(int a,int b){return a+b<mod?a+b:a+b-mod;}
int sub(int a,int b){return a<b?a-b+mod:a-b;}
int mul(int a,int b){return 1ll*a*b%mod;}
int power(int a,int b)
{
int ans=1;
for(;b;b>>=1,a=mul(a,a)) if(b&1) ans=mul(ans,a);
return ans;
}
void init(int upr)
{
for(lim=1,l=0;lim<upr;lim<<=1,l++);
for(int i=0; i<lim; i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
}
void dft(int *A,int tp){
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)
for(int j=0,r=i<<1,Wn=power(3,mod-1+tp*(mod-1)/r); j<lim; j+=r)
for(int k=0,w=1; k<i; k++,w=mul(w,Wn))
{
int x=A[j+k],y=mul(A[i+j+k],w);
A[j+k]=add(x,y);A[i+j+k]=sub(x,y);
}
if(tp==-1)
{
int linv=power(lim,mod-2);
for(int i=0; i<lim; i++) A[i]=mul(A[i],linv);
}
}
namespace DIF
{
void solve()
{
for(int i=0; i<n; i++) if(i&1) a[i]=(mod-a[i])%mod;
for(int i=0; i<=k; i++) b[i]=mul(invfac[i],invfac[k-i]);
init(n<<1);
dft(a,1);dft(b,1);
for(int i=0; i<lim; i++) a[i]=mul(a[i],b[i]);
dft(a,-1);
for(int i=0; i<n; i++)
{
int prod=mul(fac[k],a[i]);
if(i&1) prod=(mod-prod)%mod;
printf("%d ",prod);
}
}
}
namespace PRE
{
void solve()
{
for(int i=0; i<n; i++) b[i]=mul(fac[i+k-1],invfac[i]);
init(n<<1);
dft(a,1);dft(b,1);
for(int i=0; i<lim; i++) a[i]=mul(a[i],b[i]);
dft(a,-1);
for(int i=0; i<n; i++) printf("%d ",mul(a[i],invfac[k-1]));
}
}
int main()
{
scanf("%d%d%d",&n,&k,&tp);
for(int i=0; i<n; i++) scanf("%d",&a[i]);
fac[0]=1;
for(int i=1; i<=n+k; i++) fac[i]=mul(fac[i-1],i);
invfac[n+k]=power(fac[n+k],mod-2);
for(int i=n+k-1; i>=0; i--) invfac[i]=mul(invfac[i+1],i+1);
if(tp) DIF::solve();
else PRE::solve();
}