开根不过样例,求调!!!(玄关)
  • 板块灌水区
  • 楼主exCat
  • 当前回复3
  • 已保存回复3
  • 发布时间2024/7/26 19:33
  • 上次更新2024/7/26 21:02:01
查看原帖
开根不过样例,求调!!!(玄关)
361932
exCat楼主2024/7/26 19:33

求逆和乘法过了,开根两天还没调出来,已经重构了一次代码,感觉可能是有些东西重复调用的问题,一直找不出来。(ntt)

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define ll long long
using namespace std;
const int g=3,p=998244353;
const ll N=4e5+10;
ll n,m,a[N],c[N],b[N],d[N],e[N],f[N],lim=1,l;
inline ll ksm(ll a, ll k) {
	ll base = 1;
	while(k) {
		if(k & 1) base = (base * a ) % p;
		a = (a * a) % p;
		k >>= 1;
	}
	return base % p;
}
void ntt(ll *a,ll type)
{
	for(ll i=0;i<lim;i++){
		if(i<c[i])swap(a[i],a[c[i]]);
	}	
	for(ll mid=1;mid<lim;mid<<=1)
	{
		ll W=ksm(g,(p-1)/(mid<<1));
		if(type==-1)W=ksm(W,p-2);
		for(ll r=mid<<1,j=0;j<lim;j+=r)
		{
			ll w=1; 
			for(ll l=0;l<mid;l++,w=(w*W)%p)
			{
				ll x=a[j+l],y=w*a[j+mid+l]%p;
				a[j+l]=(x+y+p)%p;a[j+mid+l]=(x-y+p)%p;
			}
		}
	} 
	if(type==1) return;
	ll inv=ksm(lim,p-2);
	for(ll i=0;i<lim;i++)a[i]=(a[i]*inv)%p; 
}
void mul(ll *a,ll *b,int len1,int len2)
{
	ll l=0;
	while(lim<=len1+len2)
	{
		lim<<=1;
		l++;
	}
	for(ll i=0;i<lim;i++)c[i]=(c[i>>1]>>1)|((i&1)<<(l-1));
	ntt(a,1);ntt(b,1);
	for(ll i=0;i<lim;i++)
		a[i]=a[i]*b[i]%p;
	ntt(a,-1);
	ll inv=ksm(lim,p-2);
	for(ll i=0;i<=n+m;i++)a[i]=a[i]*inv;
	for(ll i=n+m+1;i<lim;i++)a[i]=0;
}
void inv(ll *a,ll *b,int len) 
{
	if(len==1)
	{
		b[0]=ksm(a[0],p-2);
		return ;
	}
	inv(a,b,(len+1)>>1);
	l=0,lim=1;
	while(lim<len*2)
	{
		lim<<=1;
		l++;
	}
	for(int i=0;i<len;++i)d[i]=a[i];
	for(int i=len;i<lim;i++)d[i]=0;
	for(ll i=0;i<lim;i++)c[i]=(c[i>>1]>>1)|((i&1)<<(l-1));
	ntt(a,1),ntt(d,1);ntt(b,1);
	for(ll i=0;i<lim;i++)
		b[i]=1ll*(2-1ll*d[i]*b[i]%p+p)%p*b[i]%p;
	ntt(b,-1);
	for(ll i=len;i<lim;i++)b[i]=0; 
}
void sqrt(ll *a,ll *b,int len) 
{
	if(len==1)
	{
		b[0]=1;
		return ;
	}
	sqrt(a,b,(len+1)>>1);
	l=0,lim=1;
	while(lim<len*2)
	{
		lim<<=1;
		l++;
	}
	for(int i=0;i<lim;++i)d[i]=2*b[i]%p,e[i]=b[i],f[i]=0;
	for(int i=len;i<lim;i++)e[i]=0;
	mul(b,e,lim,lim);
	inv(d,f,len);
	ntt(b,1);ntt(a,1);
	for(ll i=0;i<lim;i++)
		b[i]=(b[i]+a[i]+p)%p;
	ntt(b,-1);
	mul(b,f,lim,lim);
	for(int i=len;i<lim;i++)b[i]=0;
	return ;
}
int main()
{
	scanf("%d",&n);
	int x;
	for(ll i=0;i<n;i++)scanf("%d",&x),a[i]=(x+p)%p;
	sqrt(a,b,n);
	for(int i=0;i<n;i++)printf("%d ",b[i]); 
	return 0;
} 
2024/7/26 19:33
加载中...