# HDU 6900 Residual Polynomial【分治 NTT】

HDU 6900 Residual Polynomial

#### 题意：

$n\le 10^5, 0\leq a_i,b_i,c_i < 998244353$

#### 题解：

$\begin{array}{cccc} f_{1,0} & f_{2,0} & f_{3,0} & \cdots & f_{n0,} \\\ f_{1,1} & f_{2,1} & f_{3,1} & \cdots & f_{n,1}\\\ \vdots & \vdots & \vdots &\ddots & \vdots \\\ f_{1,n} & f_{2,n} & f_{3,n} & \cdots & f_{n,n} \end{array}$

$\begin{cases} f_{i,j}\stackrel{c_{i+1}}{\longrightarrow}f_{i+1,j} & i<n \\\ f_{i,j}\stackrel{j\cdot b_{i+1}}{\longrightarrow} f_{i+1,j-1} & i<n , j>0 \end{cases}$

$F(l,r,x)$表示在区间$[l,r)$中选$x$$b_k$的所有方案的和，那么可以得到$F(l,r,x)=\sum_{i+j=x}F(l,mid,i)\cdot F(mid,r,j)$，其中$mid = \lfloor \frac{l+r}2\rfloor$

view code
//#pragma GCC optimize("O3")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MOD = 998244353;
const int FFTN = 1<<19;
const int MAXN = 2e5+7;
#define poly vector<int>
typedef unsigned long long int ull;
int ksm(int a, int b){
int ret = 1;
while(b){
if(b&1) ret = 1ll * ret * a % MOD;
b >>= 1;
a = 1ll * a * a % MOD;
}
return ret;
}
namespace FFT{
int w[FFTN+5],W[FFTN+5],R[FFTN+5];
void FFTinit(){
W[0]=1;
W[1]=ksm(3,(MOD-1)/FFTN);
for(int i = 2; i <= FFTN; i++) W[i]=1ll*W[i-1]*W[1]%MOD;
}
int FFTinit(int n){
int L=1;
for (;L<=n;L<<=1);
for(int i = 0; i <= L - 1; i++) R[i]=(R[i>>1]>>1)|((i&1)?(L>>1):0);
return L;
}
int A[FFTN+5],B[FFTN+5];
ull p[FFTN+5];
void DFT(int *a,int n){
for(int i = 0; i < n; i++) p[R[i]]=a[i];
for(int d = 1; d < n; d <<= 1){
int len=FFTN/(d<<1);
for(int i = 0, j = 0; i < d; i++, j += len) w[i]=W[j];
for(int i = 0; i < n; i += (d<<1))
for (int j = 0; j < d; j++){
int y=p[i+j+d]*w[j]%MOD;
p[i+j+d]=p[i+j]+MOD-y;
p[i+j]+=y;
}
if (d==1<<15)
for(int i = 0; i < n; i++) p[i]%=MOD;
}
for(int i = 0; i < n; i++) a[i]=p[i]%MOD;
}
void IDFT(int *a,int n){
for(int i = 0; i < n; i++) p[R[i]]=a[i];
for (int d=1;d<n;d<<=1){
int len=FFTN/(d<<1);
for (int i=0,j=FFTN;i<d;i++,j-=len) w[i]=W[j];
for (int i=0;i<n;i+=(d<<1))
for (int j=0;j<d;j++){
int y=p[i+j+d]*w[j]%MOD;
p[i+j+d]=p[i+j]+MOD-y;
p[i+j]+=y;
}
if (d==1<<15)
for(int i = 0; i < n; i++) p[i]%=MOD;
}
int val=ksm(n,MOD-2);
for(int i = 0; i < n; i++) a[i]=p[i]*val%MOD;
}
poly Mul(const poly &a,const poly &b){
int sza=a.size()-1,szb=b.size()-1;
poly ans(sza+szb+1);
if (sza<=30||szb<=30){
for(int i = 0; i <= sza; i++) for(int j = 0; j <= szb; j++)
ans[i+j]=(ans[i+j]+1ll*a[i]*b[j])%MOD;
return ans;
}
int L=FFTinit(sza+szb);
for(int i = 0; i < L; i++) A[i]=(i<=sza?a[i]:0);
for(int i = 0; i < L; i++) B[i]=(i<=szb?b[i]:0);
DFT(A,L); DFT(B,L);
for(int i = 0; i < L; i++) A[i]=1ll*A[i]*B[i]%MOD;
IDFT(A,L);
for(int i = 0; i <= sza + szb; i++) ans[i]=A[i];
return ans;
}
}
int fac[MAXN], rfac[MAXN], inv[MAXN];
poly divide(int l, int r, vector<int> &B, vector<int> &C){ return l + 1 == r ? poly({C[l],B[l]}) : FFT::Mul(divide(l,(l+r)>>1,B,C), divide((l+r)>>1,r,B,C)); }
void solve(){
int n; scanf("%d",&n);
vector<int> A(n+1), B(n-1), C(n-1);
for(int &x : A) scanf("%d",&x);
for(int &x : B) scanf("%d",&x);
for(int &x : C) scanf("%d",&x);
poly f = divide(0,n-1,B,C);
reverse(A.begin(),A.end());
for(int i = 0; i <= n; i++) A[i] = 1ll * A[i] * fac[n-i] % MOD;
poly W = FFT::Mul(A,f);
for(int i = 0; i <= n; i++) W[i] = 1ll * W[i] * rfac[n-i] % MOD;
for(int i = n; i >= 0; i--) printf("%d%c",W[i]," \n"[!i]);
}
int main(){
fac[0] = rfac[0] = inv[1] = 1;
for(int i = 1; i < MAXN; i++) fac[i] = 1ll * fac[i-1] * i % MOD;
for(int i = 2; i < MAXN; i++) inv[i] = 1ll * (MOD - MOD / i) * inv[MOD % i] % MOD;
for(int i = 1; i < MAXN; i++) rfac[i] = 1ll * rfac[i-1] * inv[i] % MOD;
FFT::FFTinit();
int tt; for(scanf("%d",&tt); tt--; solve());
return 0;
}

posted @ 2020-09-20 23:28  _kiko  阅读(493)  评论(0编辑  收藏