【多項式】CQBZOJ 3773 多項式計算五合一
阿新 • • 發佈:2019-01-08
題意:
分析:
紅紅火火恍恍惚惚
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 800010
#define MOD 998244353
using namespace std;
int W1[40],W0[40];
int fsp(int x,int y){
int res=1;
while (y){
if(y&1)
res=1ll*res*x%MOD;
x=1ll*x*x%MOD;
y>>=1;
}
return res;
}
void ntt(int A[],int N,int flag){
for(int i=1,j=0;i<N;i++){
for(int d=N;j^=d>>=1,~j&d;);
if(i<j)
swap(A[i],A[j]);
}
for(int i=1,id=0;i<N;i<<=1,id++){
int wn;
if(flag) wn=W1[ id];
else wn=W0[id];
for(int j=0;j<N;j+=i<<1)
for(int k=0,w=1;k<i;k++,w=1ll*w*wn%MOD){
int x=A[j+k],y=1ll*w*A[i+j+k]%MOD;
A[j+k]=(x+y)%MOD;
A[i+j+k]=(x-y+MOD)%MOD;
}
}
if(flag){
int invN=fsp(N,MOD-2);
for(int i=0;i<N;i++) A[i]=1ll*A[i]*invN%MOD;
}
}
void mul (int A[],int N,int B[],int M,int res[]){
static int tmp1[MAXN],tmp2[MAXN];
for(int i=0;i<N;i++) tmp1[i]=A[i];
for(int i=0;i<N;i++) tmp2[i]=B[i];
int p=1;while(p<N+M) p<<=1;
ntt(tmp1,p,0);
ntt(tmp2,p,0);
for(int i=0;i<p;i++) tmp1[i]=1ll*tmp1[i]*tmp2[i]%MOD;
ntt(tmp1,p,1);
for(int i=0;i<N+M;i++) res[i]=tmp1[i];
for(int i=0;i<p;i++) tmp1[i]=tmp2[i]=0;
}
void inv(int A[],int N,int B[]){
if(N==1){
B[0]=fsp(A[0],MOD-2);
return ;
}
inv(A,(N+1)>>1,B);
static int tmp1[MAXN],tmp2[MAXN];
int p=1;
while(p<N<<1) p<<=1;
for(int i=0;i<N;i++) tmp1[i]=A[i];
for(int i=0;i<(N+1)>>1;i++) tmp2[i]=B[i];
ntt(tmp1,p,0);
ntt(tmp2,p,0);
for(int i=0;i<p;i++) tmp2[i]=1ll*tmp2[i]*((2ll-1ll*tmp1[i]*tmp2[i]%MOD+MOD)%MOD)%MOD;
ntt(tmp2,p,1);
for(int i=0;i<N;i++) B[i]=tmp2[i];
for(int i=0;i<p;i++) tmp1[i]=tmp2[i]=0;
}
const int inv2=499122177;
void Sqrt(int A[],int N,int B[]){
if(N==1){
B[0]=sqrt(A[0]);
return ;
}
Sqrt(A,(N+1)>>1,B);
static int tmp1[MAXN],tmp2[MAXN],tmp3[MAXN];
int p=1;
while(p<N<<1) p<<=1;
for(int i=0;i<N;i++) tmp1[i]=A[i];
for(int i=0;i<(N+1)>>1;i++) tmp2[i]=B[i];
inv(B,N,tmp3);
for(int i=0;i<N;i++) tmp3[i]=1ll*tmp3[i]*inv2%MOD;
ntt(tmp1,p,0),ntt(tmp2,p,0),ntt(tmp3,p,0);
for(int i=0;i<p;i++) tmp2[i]=1ll*(tmp1[i]+1ll*tmp2[i]*tmp2[i]%MOD)%MOD*tmp3[i]%MOD;
ntt(tmp2,p,1);
for(int i=0;i<N;i++) B[i]=tmp2[i];
for(int i=0;i<p;i++) tmp1[i]=tmp2[i]=tmp3[i]=0;
}
void integral(int A[],int N){
for(int i=N;i>0;i--) A[i]=1ll*A[i-1]*fsp(i,MOD-2)%MOD;
A[0]=0;
}
void Der(int A[],int N){
for(int i=0;i<N;i++) A[i]=1ll*A[i+1]*(i+1)%MOD;
A[N-1]=0;
}
void logar(int A[],int N,int B[]){
static int tmp1[MAXN],tmp2[MAXN];
for(int i=0;i<N;i++) tmp1[i]=A[i];
Der(tmp1,N);
inv(A,N,tmp2);
mul(tmp1,N-1,tmp2,N,tmp1);
integral(tmp1,N-1);
for(int i=0;i<N;i++) B[i]=tmp1[i];
for(int i=0;i<4*N;i++) tmp1[i]=tmp2[i]=0;
}
void Polyexp(int A[],int N,int B[]){
if(N==1){
B[0]=1;
return ;
}
Polyexp(A,(N+1)>>1,B);
static int tmp1[MAXN];
logar(B,N,tmp1);
for(int i=0;i<N;i++) tmp1[i]=(A[i]-tmp1[i]+MOD)%MOD;
tmp1[0]++;
mul(B,N,tmp1,N,tmp1);
for(int i=0;i<N;i++) B[i]=tmp1[i];
for(int i=0;i<4*N;i++) tmp1[i]=0;
}
void Polyfsp(int A[],int N,int t,int B[]){
static int tmp[MAXN];
logar(A,N,tmp);
for(int i=0;i<N;i++) tmp[i]=1ll*tmp[i]*t%MOD;
Polyexp(tmp,N,B);
}
const int G=3;
void prepare(){
for(int i=0;i<20;i++) W1[i]=fsp(G,(MOD-1)/(1<<(i+1)));
for(int i=0;i<20;i++) W0[i]=fsp(W1[i],MOD-2);
}
int a[MAXN],tmpx[MAXN];
int main(){
prepare();
int n,t;
SF("%d%d",&n,&t);
for(int i=0;i<n;i++) SF("%d",&a[i]);
Sqrt(a,n,tmpx);
for(int i=0;i<n;i++) a[i]=tmpx[i];
inv(a,n,tmpx);
for(int i=0;i<n;i++) a[i]=tmpx[i];
integral(a,n);
Polyexp(a,n,tmpx);
for(int i=0;i<n;i++) a[i]=tmpx[i];
// for(int i=0;i<n;i++)
// PF("%d ",a[i]);
// PF("\n");
inv(a,n,tmpx);
for(int i=0;i<n;i++) a[i]=tmpx[i];
a[0]++;
logar(a,n,tmpx);
for(int i=0;i<n;i++) a[i]=tmpx[i];
a[0]++;
Polyfsp(a,n,t,tmpx);
for(int i=0;i<n;i++) a[i]=tmpx[i];
Der(a,n);
for(int i=0;i<n;i++){
PF("%d",a[i]);
if(i!=n-1)
PF(" ");
}
}