多项式快速幂

给定(n-1)次多项式(A(x)),求(A^k(x)(mod\, x^n))

板子大全来了……

(A^k(x)=e^{k*lnA(x)})

然后(exp)(ln)板子套上去

(k)贼大记得取模,记得清空数组

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define eps (1e-8)
	const int N=5e5+10,p=998244353;
	inline int read()
	{
		int x=0;char ch,f=1;
		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
		if(ch=='-') f=0,ch=getchar();
		while(ch>='0'&&ch<='9'){x=((x<<1)+(x<<3)+ch-'0')%p;ch=getchar();}
		return f?x:-x;
	}
	int n,k;
	int a[N],b[N],c[N],z[N],f[N];
	int A[N],B[N];
	int pos[N];
	inline int fast(int x,int k)
	{
		int ret=1;
		while(k)
		{
			if(k&1) ret=ret*x%p;
			x=x*x%p;
			k>>=1;
		}
		return ret;
	}
	inline void ntt(int limit,int *a,int inv)
	{
		for(int i=0;i<limit;++i)
			if(i<pos[i]) swap(a[i],a[pos[i]]);
		for(int mid=1;mid<limit;mid<<=1)
		{
			int Wn=fast(3,(p-1)/(mid<<1));
			for(int r=mid<<1,j=0;j<limit;j+=r)
			{
				int w=1;
				for(int k=0;k<mid;++k,w=w*Wn%p)
				{
					int x=a[j+k],y=w*a[j+k+mid]%p;
					a[j+k]=(x+y)%p;
					a[j+k+mid]=(x-y+p)%p;
				}
			}
		}
		if(inv) return;
		inv=fast(limit,p-2);reverse(a+1,a+limit);
		for(int i=0;i<limit;++i) a[i]=a[i]*inv%p;
	}
	inline void deriva(int *a,int *b,int n)
	{
		for(int i=1;i<n;++i) b[i-1]=a[i]*i%p;
		b[n-1]=0;
	}
	inline void integral(int *a,int n)
	{
		for(int i=n-1;i;--i) a[i]=a[i-1]*fast(i,p-2)%p;
		a[0]=0;
	}
	inline void poly_inv(int pw,int *a,int *b)
	{
		if(pw==1){b[0]=fast(a[0],p-2);return;}
		poly_inv((pw+1)>>1,a,b);
		int len=0,limit=1;
		while(limit<(pw<<1)) limit<<=1,++len;
		for(int i=0;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(len-1));
		for(int i=0;i<pw;++i) c[i]=a[i];
		for(int i=pw;i<limit;++i) c[i]=0;
		ntt(limit,c,1);ntt(limit,b,1);
		for(int i=0;i<limit;++i) b[i]=((2-c[i]*b[i]%p)+p)%p*b[i]%p;
		ntt(limit,b,0);
		for(int i=pw;i<limit;++i) b[i]=0;
	}
	inline void ln(int *a,int *b,int n)
	{
		deriva(a,A,n),poly_inv(n,a,B);
		int len=0,limit=1;
		while(limit<(n<<1)) limit<<=1,++len;
		for(int i=0;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(len-1));
		ntt(limit,A,1);ntt(limit,B,1);
		for(int i=0;i<limit;++i) b[i]=A[i]*B[i]%p;
		ntt(limit,b,0);
		integral(b,limit);
		for(int i=0;i<limit;++i) A[i]=B[i]=0;
	}
	inline void exp(int pw,int *a,int *b)
	{
		if(pw==1) {b[0]=1;return;}
		exp((pw+1)>>1,a,b);ln(b,f,pw);
		int len=0,limit=1;
		while(limit<(pw<<1)) limit<<=1,++len;
		for(int i=0;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(len-1));
		f[0]=(a[0]+1-f[0])%p;
		for(int i=1;i<pw;++i) f[i]=(a[i]-f[i]+p)%p;
		ntt(limit,f,1);ntt(limit,b,1);
		for(int i=0;i<limit;++i) b[i]=b[i]*f[i]%p;
		ntt(limit,b,0);
		for(int i=pw;i<limit;++i) b[i]=f[i]=0;
	}
	inline void main()
	{
		n=read(),k=read();
		for(int i=0;i<n;++i) a[i]=read();
		ln(a,z,n);
		for(int i=0;i<n;++i) z[i]=z[i]*k%p;
		exp(n,z,b);
		for(int i=0;i<n;++i) printf("%lld ",b[i]);
	}
}
signed main()
{
	red::main();
	return 0;
}
原文地址:https://www.cnblogs.com/knife-rose/p/12131652.html