【多项式】CQBZOJ 3773 多项式计算五合一

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34454069/article/details/85679944

题意:

在这里插入图片描述


分析:

红红火火恍恍惚惚

#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(" ");
	}
}

猜你喜欢

转载自blog.csdn.net/qq_34454069/article/details/85679944
今日推荐