多项式

用来放我的多项式板子。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=4e5+10,mod=998244353;
typedef basic_string<int> poly;
int fac[N],inv[N];
poly tr;
int qpow(int x,int y)
{
	int ret=1;
	while(y)
	{
		if(y&1)
		{
			ret=ret*x%mod;
		}
		x=x*x%mod;
		y/=2;
	}
	return ret;
}
void pre(int len)
{
	fac[0]=1;
	for(int i=1;i<=len;i++)
	{
		fac[i]=fac[i-1]*i%mod;
	}
	inv[len]=qpow(fac[len],mod-2);
	for(int i=len-1;i>=0;i--)
	{
		inv[i]=inv[i+1]*(i+1)%mod;
	}
}
poly ntt(poly ar,int fl)
{
	int g=3,invg,len=ar.size();
	invg=qpow(g,mod-2);
	for(int i=0;i<len;i++)
	{
		if(tr[i]>i)
		{
			swap(ar[i],ar[tr[i]]);
		}
	}
	for(int l=2;l<=len;l*=2)
	{
		int mid=l/2,W=qpow((fl==1? g:invg),(mod-1)/l),w=1;
		for(int i=0;i+l<=len;i+=l)
		{
			for(int j=i,w0=w;j<i+mid;j++,w0=w0*W%mod)
			{
				int x=ar[j],y=w0*ar[j+mid]%mod;
				ar[j]=(x+y);ar[j+mid]=(x-y+mod);
				if(ar[j]>mod)
				{
					ar[j]-=mod;
				}
				if(ar[j+mid]>mod)
				{
					ar[j+mid]-=mod;
				}
			}
		}
	}
	return ar;
}
poly mul(poly x,poly y)
{
	int len=1;
	while(len<x.size()+y.size())
	{
		len*=2;
	}
	x.resize(len);y.resize(len);
	tr.resize(len);
	tr[0]=0;
	for(int i=1;i<len;i++)
	{
		tr[i]=(tr[i>>1]>>1)+(i%2)*len/2;
	}
	x=ntt(x,1);
	y=ntt(y,1);
	for(int i=0;i<len;i++)
	{
		x[i]=x[i]*y[i]%mod;
	}
	x=ntt(x,-1);
	int iv=qpow(len,mod-2);
	for(int i=0;i<len;i++)
	{
		x[i]=x[i]*iv%mod;
	}
	while(len>1)
	{
		if(x[len-1]!=0)
		{
			break;
		}
		len--;
	}
	x.resize(len);
	return x;
}
poly getinv(poly ar)
{
	int len=1,l2=ar.size();
	poly b1,t1,t2;
	while(len<l2)
	{
		len*=2;
	}
	ar.resize(len);b1.resize(1);
	b1[0]=qpow(ar[0],mod-2);
	for(int i=2;i<=len;i*=2)
	{
		t2=b1;
		t2.resize(i);
		for(int j=0;j<i/2;j++)
		{
			t2[j]=t2[j]*2%mod;
		}
		b1=mul(b1,b1);
		t1=ar;
		t1.resize(i);
		b1=mul(b1,t1);
		b1.resize(i);
		for(int j=0;j<i;j++)
		{
			b1[j]=t2[j]-b1[j]+mod;
			if(b1[j]>=mod)
			{
				b1[j]-=mod;
			}
		}
	}
	b1.resize(l2);
	return b1;
}
poly getdao(poly ar,int x)
{
	int len=ar.size()-x;
	for(int i=0;i<len;i++)
	{
		ar[i]=ar[i+x]*fac[i+x]%mod*inv[i]%mod;
	}
	if(len)
	{
		ar.resize(len);
	}else
	{
		ar.resize(1);
		ar[0]=0;
	}
	return ar;
}
poly getji(poly ar,int x)
{
	int len=ar.size()+x;
	ar.resize(len);
	for(int i=len-1;i>=x;i--)
	{
		ar[i]=ar[i-x]*inv[i]%mod*fac[i-x]%mod;
	}
	for(int i=0;i<x;i++)
	{
		ar[i]=0;
	}
	return ar;
}
poly getln(poly ar)
{
	poly t1;
	int len=ar.size();
	t1=getdao(ar,1);
	ar=getinv(ar);
	ar=mul(ar,t1);
	ar=getji(ar,1);
	ar.resize(len);
	return ar;
}
poly getexp(poly ar)
{
	int len=1,l2=ar.size();
	int l1=ar.size();
	while(len<l1)
	{
		len*=2;
	}
	ar.resize(len);
	poly t1,b1;
	b1.resize(1);b1[0]=1;
	for(int i=2;i<=len;i*=2)
	{
		t1=b1;
		t1.resize(i);
		t1=getln(t1);
		for(int j=0;j<i;j++)
		{
			t1[j]=ar[j]-t1[j]+mod;
			if(t1[j]>=mod)
			{
				t1[j]-=mod;
			}
		}
		t1[0]++;
		if(t1[0]>=mod)
		{
			t1[0]-=mod;
		}
		b1=mul(t1,b1);
		b1.resize(i);
	}
	b1.resize(l1);
	return b1;
}
poly getrev(poly x)
{
	int len=x.size();
	for(int i=0;i*2+1<len;i++)
	{
		swap(x[i],x[len-i-1]);
	}
	return x;
}
pair<poly,poly> getmod(poly x,poly y)
{
	int l1=x.size(),l2=y.size();
	if(l1<l2)
	{
		y.resize(1);
		y[0]=0;
		return make_pair(y,x);
	}
	int l3=l1-l2+1;
	poly t1,t2;
	t1=getrev(x);
	t2=getrev(y);
	t1.resize(l3);t2.resize(l3);
	t2=getinv(t2);
	t1=mul(t1,t2);
	t1.resize(l3);
	t1=getrev(t1);
	y.resize(l2-1);
	t2=t1;
	if(l3>l2-1)
	{
		t2.resize(l2-1);
	}
	t2=mul(y,t2);
	for(int i=0;i<l2-1;i++)
	{
		t2[i]=x[i]-t2[i]+mod;
		if(t2[i]>=mod)
		{
			t2[i]-=mod;
		}
	}
	t2.resize(l2-1);
	return make_pair(t1,t2);
}
poly qp(poly x,int ts,poly y)
{
	poly ret,tmp;
	int len=y.size();
	ret.resize(1);
	ret[0]=1;
	while(ts)
	{
		if(ts&1)
		{
			ret=mul(ret,x);
			if(ret.size()>len*2)
			{
				ret.resize(len*2);
			}
			ret=getmod(ret,y).second;
		}
		x=mul(x,x);
		if(x.size()>len*2)
		{
			x.resize(len*2);
		}
		x=getmod(x,y).second;
		ts/=2;
	}
	return ret;
}
posted @ 2025-02-11 12:50  ethan0328  阅读(5)  评论(0)    收藏  举报