多项式全家桶

#include<bits/stdc++.h>
#define LL long long
using namespace std;
namespace Poly
{
	const int mod=998244353,_G=3,_Gi=332748118,Mx=2100000;
	int _w[Mx+2],_inv[Mx+2],FAC[Mx+2],INV[Mx+2];
	typedef pair<int,int> P;
	mt19937 _rnd(0);
	inline void Print(vector<int> A)
	{
		for(int i=0;i<A.size();++i)printf("%d ",A[i]);
		puts("");
	}
	inline LL Pow(LL a,int b)
	{
		LL c=1;
		for(;b;b>>=1,(a*=a)%=mod)if(b&1)(c*=a)%=mod;
		return c;
	}
	inline void add(int &x,int y)
	{
		if((x+=y)>=mod)x-=mod;
	}
	inline vector<int> Add(vector<int> A,vector<int> B)
	{
		int n=max(A.size(),B.size());
		A.resize(n),n=B.size();
		for(int i=0;i<n;++i)add(A[i],B[i]);
		return A;
	}
	inline vector<int> Mul(vector<int> A,int k)
	{
		if(k<0)k+=mod;
		for(int i=0;i<A.size();++i)A[i]=((LL)A[i]*k)%mod;
		return A;
	}
	inline void Init()
	{
		int len,mid,W;
		len=(1<<(int)log2(Mx)),mid=len>>1,W=Pow(_G,(mod-1)/len),_w[mid]=_inv[1]=1;
		for(int i=2;i<=Mx;++i)_inv[i]=((LL)(mod-mod/i)*_inv[mod%i])%mod;
		for(int i=mid+1;i<len;++i)_w[i]=((LL)_w[i-1]*W)%mod;
		for(int i=mid-1;i>=0;--i)_w[i]=_w[i<<1];
		FAC[0]=INV[0]=1;for(int i=1;i<=Mx;++i)FAC[i]=((LL)FAC[i-1]*i)%mod,INV[i]=((LL)INV[i-1]*_inv[i])%mod;
	}
	inline LL Binom(int a,int b)
	{
		return (LL)FAC[a]*INV[b]%mod*INV[a-b]%mod;
	}
	inline void DFT(vector<int> &A)
	{
		int n=A.size(),tmp;
		for(int i=(n>>1);i;i>>=1)for(int j=0;j<n;j+=(i<<1))for(int k=0;k<i;++k)tmp=A[i+j+k],A[i+j+k]=((LL)(A[j+k]-tmp+mod)*_w[i+k])%mod,add(A[j+k],tmp);
	}
	inline void IDFT(vector<int> &A)
	{
		int n=A.size(),tmp;
		for(int i=1;i<n;i<<=1)for(int j=0;j<n;j+=(i<<1))for(int k=0;k<i;++k)tmp=((LL)A[i+j+k]*_w[i+k])%mod,add(A[i+j+k]=A[j+k],mod-tmp),add(A[j+k],tmp);
		for(int i=1;i<n-i;++i)swap(A[i],A[n-i]);
	}
	inline vector<int> Mul(vector<int> A,vector<int> B)
	{
		int n=A.size()-1,m=B.size()-1,len,inv;
		for(len=1;len<=n+m;len<<=1);
		inv=_inv[len],A.resize(len),B.resize(len),DFT(A),DFT(B);
		for(int i=0;i<len;++i)A[i]=((LL)A[i]*B[i])%mod;
		IDFT(A),A.resize(n+m+1);
		for(int i=0;i<A.size();++i)A[i]=((LL)A[i]*inv)%mod;
		return A;
	}
	inline vector<int> Mul2(vector<int> A)
	{
		int n=A.size()-1,len,inv;
		for(len=1;len<=n+n;len<<=1);
		inv=_inv[len],A.resize(len),DFT(A);
		for(int i=0;i<len;++i)A[i]=((LL)A[i]*A[i])%mod;
		IDFT(A),A.resize(n+n+1);
		for(int i=0;i<A.size();++i)A[i]=((LL)A[i]*inv)%mod;
		return A;
	}
	inline vector<int> Inv(vector<int> &A,int k)
	{
		vector<int> B,C;
		B.push_back(Pow(A[0],mod-2));
		for(int l=2,x;l<=(k<<1);l<<=1)
		{
			C.resize(x=min(l,(int)A.size()));
			for(int i=0;i<x;++i)C[i]=A[i];
			C=Mul(Mul(C,B),-1),add(C[0],2),(B=Mul(B,C)).resize(l);
		}
		return B.resize(k),B;
	}
	inline int Cipolla(int k)
	{
		if(!k)return 0;
		int a,b=((mod+1)>>1),I;
		for(;Pow((a=abs((int)_rnd()),I=((((LL)a*a-k)%mod)+mod)%mod),(mod-1)>>1)==1;);
		P p=P(1,0),t=P(a,1);
		for(;b;b>>=1)
		{
			if(b&1)p=P(((LL)p.first*t.first+(((LL)p.second*t.second)%mod)*I)%mod,((LL)p.first*t.second+(LL)t.first*p.second)%mod);
			t=P(((LL)t.first*t.first+(((LL)t.second*t.second)%mod)*I)%mod,((LL)t.first*t.second*2)%mod);
		}
		return min(p.first,mod-p.first);
	}
	inline vector<int> Sqrt(vector<int> &A,int k)
	{
		vector<int> B,C;
		B.push_back(Cipolla(A[0]));
		for(int l=2,x;l<=(k<<1);l<<=1)
		{
			C.resize(x=min(l,(int)A.size()));
			for(int i=0;i<x;++i)C[i]=A[i];
			(B=Mul(Mul(Add(Mul(B,B),C),Inv(B,l)),(mod+1)/2)).resize(l);
		}
		return B.resize(k),B;
	}
	inline vector<int> Der(vector<int> A)
	{
		for(int i=1;i<A.size();++i)A[i-1]=((LL)A[i]*i)%mod;
		return A.pop_back(),A;
	}
	inline vector<int> Int(vector<int> A)
	{
		A.push_back(0);
		for(int i=A.size()-1;i;--i)A[i]=((LL)A[i-1]*_inv[i])%mod;
		return A[0]=0,A;
	}
	inline vector<int> Ln(vector<int> A,int k)
	{
		return (A=Int(Mul(Der(A),Inv(A,k)))).resize(k),A;
	}
	inline vector<int> Exp(vector<int> &A,int k)
	{
		vector<int> B,C;
		B.push_back(1);
		for(int l=2,x;l<=(k<<1);l<<=1)
		{
			C.resize(x=min(l,(int)A.size()));
			for(int i=0;i<x;++i)C[i]=A[i];
			C=Add(C,Mul(Ln(B,l),-1)),add(C[0],1),(B=Mul(B,C)).resize(l);
		}
		return B.resize(k),B;
	}
	inline vector<int> Pow(vector<int> A,char *s,int k)
	{
		int t,b=0,b2=0,a,inv,l=strlen(s+1);
		LL tmp;
		for(int i=1;i<=l;++i)tmp=(LL)b*10+(s[i]^48),b=(tmp<mod? tmp:(tmp%mod)+mod),tmp=(LL)b2*10+(s[i]^48),b2=(tmp<mod-1? tmp:(tmp%(mod-1))+mod-1);
		for(t=0;t<A.size() && !A[t];++t);
		if(t==A.size() || (t && b2>A.size()/t) || k<=t)return A.resize(0),A.resize(k),A;
		inv=Pow(a=A[t],mod-2);
		for(int i=t;i<A.size();++i)A[i-t]=((LL)A[i]*inv)%mod;
		A.resize(k-t),(A=Mul(Exp(A=Mul(Ln(A,k),b),k),Pow(a,b2))).resize(A.size()+(t*=b2));
		for(int i=A.size()-1;i>=t;--i)A[i]=A[i-t];
		for(int i=0;i<t;++i)A[i]=0;
		return A.resize(k),A;
	}
	inline vector<int> Pow(vector<int> A,LL s,int k)
	{
		int t,b=(s<mod? s:(s%mod)+mod),b2=(s<mod-1? s:(s%(mod-1))+mod-1),a,inv;
		for(t=0;t<A.size() && !A[t];++t);
		if(t==A.size() || (t && b2>A.size()/t) || k<=t)return A.resize(0),A.resize(k),A;
		inv=Pow(a=A[t],mod-2);
		for(int i=t;i<A.size();++i)A[i-t]=((LL)A[i]*inv)%mod;
		A.resize(k-t),A=Mul(Exp(A=Mul(Ln(A,k),b),k),Pow(a,b2)),t*=b2,A.resize(k);
		for(int i=k-1;i>=t;--i)A[i]=A[i-t];
		for(int i=min(t,k)-1;~i;--i)A[i]=0;
		return A;
	}
	inline void Rev(vector<int> &A)
	{
		for(int i=0;(i<<1)+1<A.size();++i)swap(A[i],A[A.size()-i-1]);
	}
	inline vector<int> Div(vector<int> A,vector<int> B)
	{
		int n=A.size(),m=B.size();
		if(n<m)return vector<int>{0};
		return Rev(A),Rev(B),(A=Mul(A,Inv(B,n-m+1))).resize(n-m+1),Rev(A),A;
	}
	inline vector<int> Mod(vector<int> A,vector<int> &B)
	{
		if(A.size()<B.size())return A;
		return (A=Add(A,Mul(Mul(B,Div(A,B)),-1))).resize(B.size()-1),A;
	}
	inline vector<int> Shift(vector<int> A,int c)
	{
		int n=A.size();
		vector<int> B;
		B.resize(n),c=(c%mod+mod)%mod;
		for(int i=0;i<n;++i)A[i]=((LL)A[i]*FAC[i])%mod,B[i]=(i? (LL)B[i-1]*c%mod*_inv[i]%mod:1)%mod;
		Rev(A),A=Mul(A,B),A.resize(n),Rev(A);
		for(int i=0;i<n;++i)A[i]=((LL)A[i]*INV[i])%mod;
		return A;
	}
	inline void Maintain(vector<int> &A)
	{
		int n=A.size(),t=0;
		for(int i=0;i<n;++i)add(A[i],mod+t),t=A[i]/10,A[i]%=10;
		for(;t;t/=10)A.push_back(t%10);
	}
	inline bool Cmp(vector<int> &A,vector<int> &B)
	{
		int n=A.size();
		if(n<B.size())return 1;
		if(n>B.size())return 0;
		for(int i=n-1;~i;--i)
		{
			if(A[i]<B[i])return 1;
			if(A[i]>B[i])return 0;
		}
		return 0;
	}
	inline void Solve()
	{
		Init();
		
	}
};
int main()
{
	Poly::Solve();
	return 0;
}

把相关代码放在 solve 函数里即可运行。

posted @ 2022-06-26 22:27  18Michael  阅读(64)  评论(0编辑  收藏  举报