多项式板子(待完善)

namespace polynomial
{
	const ll N=1e7+50,G=3,mod=998244353;
	ll r[N],tmp[N];
	inline ll ksmod(ll a,ll b)
	{
		ll ans=1;
		while(b)
		{
			if(b&1) ans=(ans*a)%mod;
			a=(a*a)%mod;
			b>>=1;
		}
		return ans%mod;
	}
	inline void ntt(ll *a,ll limit,ll pd)
	{
		fr(i,0,limit-1) if(i<r[i]) swap(a[i],a[r[i]]);
		for(ll i=1;i<limit;i<<=1)
		{
			ll gn=ksmod(G,(mod-1)/(i<<1));
			for(ll j=0;j<limit;j+=(i<<1))
			{
				ll g=1;
				for(ll k=0;k<i;++k,g=(g*gn)%mod)
				{
				 	ll x=a[j+k],y=g*a[j+k+i]%mod;
					a[j+k]=(x+y)%mod,a[j+k+i]=(x-y+mod)%mod;
				}
			}
		}
		if(pd==1) return ;
		ll inv=ksmod(limit,mod-2);
		reverse(a+1,a+limit);
		fr(i,0,limit-1) a[i]=a[i]*inv%mod;
	}
	inline void polyinv(ll n,ll *a,ll *b)
	{
		if(n==1)
		{
			b[0]=ksmod(a[0],mod-2);
			return ;
		}
		polyinv((n+1)>>1,a,b);
		static ll l=0,limit=1;
		while(limit<(n<<1)) limit<<=1,++l;
		fr(i,1,limit-1) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
		fr(i,0,n-1) tmp[i]=a[i];
		fr(i,n,limit-1) tmp[i]=0;
		ntt(b,limit,1),ntt(tmp,limit,1);
		fr(i,0,limit-1) b[i]=(2*b[i]%mod-(b[i]*b[i]%mod*tmp[i])%mod+mod)%mod;
		ntt(b,limit,-1);
		fr(i,n,limit-1) b[i]=0; 
	}
	inline void polyderi(ll n,ll *a)
	{
		fr(i,1,n) a[i-1]=(a[i]*i)%mod;
		a[n]=0;
	}
	inline void polyinte(ll n,ll *a)
	{
		pfr(i,n,1) a[i]=(a[i-1]*ksmod(i,mod-2))%mod;
		a[0]=0;
	}
	ll b[N],ans[N];
	inline void polyln(ll n,ll *a)
	{
		memcpy(b,a,sizeof(b));
		polyderi(n,a),polyinv(n,b,ans);
		ll limit=1,l=0;
		while(limit<=(n<<1)) limit<<=1,++l;
		fr(i,0,limit-1) b[i]=ans[i];
		fr(i,1,limit-1) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
		ntt(a,limit,1),ntt(b,limit,1);
		fr(i,0,limit) a[i]=(a[i]*b[i])%mod;
		ntt(a,limit,-1);
		polyinte(n,a);
		fr(i,n+1,limit) a[i]=0;
	}
}
using namespace polynomial;

猜你喜欢

转载自www.cnblogs.com/lgj-lgj/p/13392147.html