社区讨论

有没有大佬帮我卡卡常qwq

P5205【模板】多项式开根参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@locju14a
此快照首次捕获于
2023/10/30 14:58
2 年前
此快照最后确认于
2023/11/05 02:14
2 年前
查看原帖
直接提交过不去,开了O2才过。是我写的太丑了嘛。有没有大佬帮我看看求逆和开根是不是哪里写炸了?qwq
CPP
#include<cstdio>
#define reg register
const int MaxN=800000,g=3,gi=332748118,mod=998244353,inv2=499122177;
inline void read(int &ans)
{
	ans=0;
	char c=getchar();
	while(c<'0'||c>'9')
		c=getchar();
	while(c>='0'&&c<='9')
		ans=ans*10+c-48,c=getchar();
	return;
}
int n;
struct poly
{
	int val[MaxN+1];
	inline int &operator [] (const int &k) {return val[k];}
};
inline void swap(int &a,int &b)
{
	const int t=a;
	a=b,b=t;
	return;
}
inline int add(const int &a,const int &b)
{
	const int s=a+b;
	return s<mod?s:s-mod;
}
inline int multi(const int &a,const int &b)
{
	return 1ll*a*b%mod;
}
inline int pwo(int a,int b)
{
	int s=1;
	while(b)
	{
		if(b&1)
			s=multi(s,a);
		a=multi(a,a),b>>=1;
	}
	return s;
}
int exgcd(const int &a,const int &b,int &x,int &y)
{
	if(!b)
		return x=1,y=0,a;
	int gcd=exgcd(b,a%b,y,x);
	return y-=a/b*x,gcd;
}
inline int inverse(const int &a)
{
	int x,y;
	return exgcd(a,mod,x,y),add(x,mod);
}
void NTT(poly &a,int lg,int lm,int mode)
{
	static int r[MaxN+1];
	for(reg int i=1;i<lm;++i)
	{
		r[i]=(r[i>>1]>>1)|((i&1)<<lg-1);
		if(r[i]<i)
			swap(a[r[i]],a[i]);
	}
	for(reg int len=2,mid=1,i,j,k,w,mi,x,y;len<=lm;len<<=1,mid<<=1)
		for(i=0,w=pwo(~mode?g:gi,(mod-1)/len);i<lm;i+=len)
			for(j=0,mi=1;j<mid;++j,mi=multi(mi,w))
				x=a[i+j],y=multi(mi,a[i+mid+j]),a[i+j]=add(x,y),a[i+mid+j]=add(x,mod-y);
	if(!~mode)
		for(reg int i=0,inv=inverse(lm);i<lm;++i)
			a[i]=multi(a[i],inv);
	return;
}
void inverse(poly &f,poly &g,int n)
{
	static poly f0;
	int lm=2,lg=1,len=1;
	g[0]=inverse(f[0]);
	while(len<=n)
	{
		++lg,lm<<=1,len<<=1;
		for(reg int i=0;i<len;++i)
			f0[i]=f[i];
		for(reg int i=len;i<lm;++i)
			f0[i]=0;
		for(reg int i=len>>1;i<lm;++i)
			g[i]=0;
		NTT(f0,lg,lm,1),NTT(g,lg,lm,1);
		for(reg int i=0;i<lm;++i)
			g[i]=multi(g[i],add(2,mod-multi(f0[i],g[i])));
		NTT(g,lg,lm,-1);
	}
	for(reg int i=n+1;i<lm;++i)
		g[i]=0;
	return;
}
void sqrt(poly &f,poly &g,int n)
{
	static poly f0,h;
	int lm=2,lg=1,len=1;
	g[0]=1;
	while(len<=n)
	{
		++lg,lm<<=1,len<<=1;
		for(reg int i=0;i<len;++i)
			f0[i]=f[i];
		inverse(g,h,len);
		NTT(f0,lg,lm,1),NTT(h,lg,lm,1);
		for(reg int i=0;i<lm;++i)
			f0[i]=multi(f0[i],h[i]);
		NTT(f0,lg,lm,-1);
		for(reg int i=0;i<len;++i)
			g[i]=multi(add(g[i],f0[i]),inv2);
	}
	for(reg int i=n+1;i<len;++i)
		g[i]=0;
	return;
}
poly f,G;
int main()
{
	read(n),n--;
	for(reg int i=0;i<=n;++i)
		read(f[i]);
	sqrt(f,G,n);
	for(reg int i=0;i<=n;++i)
		printf("%d ",G[i]);
	putchar('\n');
	return 0;
}

回复

0 条回复,欢迎继续交流。

正在加载回复...