【多项式合集】LOJ150 挑战多项式

版权声明:这是蒟蒻的BLOG,神犇转载也要吱一声哦~ https://blog.csdn.net/Dream_Lolita/article/details/88993169

【题目】
LOJ
给定 n n 次多项式 F ( x ) F(x) ,求 G ( x ) G(x) 满足:
G ( x ) ( ( 1 + ln ( 2 + F ( x ) F ( 0 ) exp ( 1 F ( x ) d x ) ) ) k ) ( mod  x n ) G(x)\equiv ((1+\ln(2+F(x)-F(0)-\exp(\int \frac {1} {\sqrt{F(x)}}dx)))^k)' \quad (\text{mod }x^n)
运算在模 998244353 998244353 下进行,保证常数项有二次剩余, F ( x ) \sqrt {F(x)} 保留常数项较小的一个。

【解题思路】
差不多是最全的板子了。
除了没有写毛爷爷 FFT \text{FFT} 以外可以适用几乎所有多项式题了吧。
板子额外补充了题里面没有的多项式除法。

复杂度常数极大的 O ( n log n ) O(n\log n)

【参考代码】

#include<bits/stdc++.h>
#define fi first
#define se second
#define mkp make_pair
using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
const int N=262333,mod=998244353,G=3;

namespace IO
{
	int read()
	{
		int ret=0;char c=getchar();
		while(!isdigit(c)) c=getchar();
		while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
		return ret;
	}
	void write(int x){if(x>9)write(x/10);putchar(x%10^48);}
	void writesp(int x){write(x);putchar(' ');}
}
using namespace IO;

namespace Math
{
	int inv[N];
	void gmin(int &x,int y){x=min(x,y);}
	void gmax(int &x,int y){x=max(x,y);}
	int upm(int x){return x>=mod?x-mod:(x<0?x+mod:x);}
	void up(int &x,int y){x=upm(x+y);}
	int mul(int x,int y){return 1ll*x*y%mod;}
	int qpow(int x,int y){int res=1;for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);return res;}
	int getinv(int x){return qpow(x,mod-2);}
	void initinv()
	{
		inv[1]=1;
		for(int i=2;i<N;++i) inv[i]=mod-mul(mod/i,inv[mod%i]);
	}
	pii mul(pii x,pii y,int val){return mkp(upm(mul(x.fi,y.fi)+mul(mul(x.se,y.se),val)),upm(mul(x.fi,y.se)+mul(x.se,y.fi)));}
	int qpow(pii x,int y,int val)
	{
		pii res=mkp(1,0);
		for(;y;y>>=1,x=mul(x,x,val))if(y&1)res=mul(res,x,val);
		return res.fi;
	}
	int calcCipolla(int x)
	{
		int y=rand()%mod;
		while(qpow(upm(mul(y,y)-x),(mod-1)/2)!=mod-1) y=rand()%mod;
		return qpow(mkp(y,1),(mod+1)/2,upm(mul(y,y)-x));
	}
}
using namespace Math;

namespace Poly
{
	int m,L,rev[N];
	void ntt(int *a,int n,int f)
	{
		for(int i=0;i<n;++i) if(i<rev[i]) swap(a[i],a[rev[i]]);
		for(int i=1;i<n;i<<=1)
		{
			int wn=qpow(G,(mod-1)/(i<<1));
			if(!~f) wn=getinv(wn);
			for(int j=0;j<n;j+=i<<1)
			{
				int w=1;
				for(int k=0;k<i;++k,w=mul(w,wn))
				{
					int x=a[j+k],y=mul(w,a[i+j+k]);
					a[j+k]=upm(x+y);a[i+j+k]=upm(x-y);
				}
			}
		}
		if(!~f) for(int i=0,inv=getinv(n);i<n;++i) a[i]=mul(a[i],inv);
	}
	void reget(int n)
	{
		for(m=1,L=0;m<=2*n;m<<=1,++L);
		for(int i=0;i<m;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
	}
	void polymul(int *a,int *b,int *c)
	{
		ntt(a,m,1);ntt(b,m,1);
		for(int i=0;i<m;++i) c[i]=mul(a[i],b[i]);
		ntt(c,m,-1);
	}
	void polyder(int *a,int deg)
	{
		for(int i=0;i<deg-1;++i) a[i]=mul(a[i+1],i+1);
		a[deg-1]=0;
	}
	void polyint(int *a,int deg)
	{
		for(int i=deg-1;i;--i) a[i]=mul(a[i-1],inv[i]);
		a[0]=0;
	}
	void polyinv(int *a,int *b,int deg)//B(x) = G(x)(2-G(x)A(x))
	{
		if(deg==1){b[0]=getinv(a[0]);return;}
		polyinv(a,b,(deg+1)>>1);
		static int A[N],B[N];
		reget(deg);copy(a,a+deg,A);fill(A+deg,A+m,0);copy(b,b+deg,B);fill(B+deg,B+m,0);
		ntt(A,m,1);ntt(B,m,1);
		for(int i=0;i<m;++i) A[i]=mul(A[i],mul(B[i],B[i]));
		ntt(A,m,-1);
		for(int i=0;i<deg;++i) b[i]=upm(mul(2,b[i])-A[i]);
		fill(A,A+m,0);fill(B,B+m,0);
	}
	void polydiv(int *a,int *b,int *c,int dega,int degb)//a/b,A^r(x)=B^r(x)D^r(x),D^r(x) we need
	{
		static int A[N],B[N];
		copy(b,b+degb,A);reverse(A,A+degb);polyinv(A,B,dega-degb+1);
		copy(a,a+dega,A);reverse(A,A+dega);
		reget(dega);polymul(A,B,A);
		for(int i=0;i<=dega-degb;++i) c[i]=A[i];
		reverse(c,c+dega-degb+1);
		fill(A,A+m,0);fill(B,B+m,0);
	}
	void polymod(int *a,int *b,int *c,int dega,int degb)
	{
		static int A[N],B[N];
		polydiv(a,b,A,dega,degb);copy(b,b+degb,B);
		reget(dega);polymul(A,B,A);
		for(int i=0;i<degb-1;++i) c[i]=upm(a[i]-A[i]);
		fill(A,A+m,0);fill(B,B+m,0);
	}
	void polyln(int *a,int *b,int deg)
	{
		static int A[N],B[N];
		polyinv(a,A,deg);copy(a,a+deg,B);polyder(B,deg);
		reget(deg);polymul(A,B,A);
		for(int i=0;i<deg;++i) b[i]=A[i];
		polyint(b,deg);
		fill(A,A+m,0);fill(B,B+m,0);
	}
	void polyexp(int *a,int *b,int deg)//newton
	{
		if(deg==1){b[0]=1;return;}
		polyexp(a,b,(deg+1)>>1);
		static int A[N],B[N];fill(A,A+deg*2,0);fill(B,B+deg*2,0);
		polyln(b,B,deg);
		for(int i=0;i<deg;++i) B[i]=(mod+(!i)-B[i]+a[i])%mod;
		copy(b,b+deg,A);reget(deg);polymul(A,B,A);
		for(int i=0;i<deg;++i) b[i]=A[i];
		fill(A,A+m,0);fill(B,B+m,0);
	}
	void polysqrt(int *a,int *b,int deg)//(B(x)=A(x)+G^2(x))/2G(x)=A(x)/2G(x)+1/2G(x)
	{
		if(deg==1){b[0]=calcCipolla(a[0]);gmin(b[0],mod-b[0]);return;}
		polysqrt(a,b,(deg+1)>>1);
		static int A[N],B[N];
		polyinv(b,B,deg);
		reget(deg);copy(a,a+deg,A);fill(A+deg,A+m,0);
		polymul(A,B,A);
		for(int i=0;i<deg;++i) b[i]=mul(inv[2],upm(b[i]+A[i]));
		fill(A,A+m,0);fill(B,B+m,0);
	}
	void polypow(int *a,int *b,int deg,int K)
	{
		static int A[N];
		polyln(a,A,deg);
		for(int i=0;i<deg;++i) A[i]=mul(A[i],K);
		polyexp(A,b,deg);
		fill(A,A+deg,0);
	}
}
using namespace Poly;

namespace DreamLolita
{
	int n,K;
	int a[N],b[N],c[N],d[N],f[N];
	void solution()
	{
		srand(19260817);initinv();
		n=read()+1;K=read();
		for(int i=0;i<n;++i) f[i]=a[i]=read();
		polysqrt(a,b,n);polyinv(b,c,n);polyint(c,n);polyexp(c,d,n);
		for(int i=0;i<n;++i) a[i]=((!i)*2+(bool)i*f[i]-d[i]+mod)%mod;
		fill(b,b+n,0);polyln(a,b,n);b[0]=1;
		fill(c,c+n,0);polypow(b,c,n,K);
		polyder(c,n);
		for(int i=0;i<n-1;++i) writesp(c[i]);
	}
}

int main()
{
#ifdef Durant_Lee
	freopen("LOJ150.in","r",stdin);
	freopen("LOJ150.out","w",stdout);
#endif
	DreamLolita::solution();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Dream_Lolita/article/details/88993169