多项式幂函数,多项式模板

多项式求 ln ⁡ \ln ln
( ln ⁡ A ( x ) ) ′ = A ′ ( x ) A ( x ) (\ln A(x))'=\frac{A'(x)}{A(x)} (lnA(x))=A(x)A(x)
算出等式右边后再积回来就行。
多项式求 e x p exp exp
定义函数 F ( G ( x ) ) = ln ⁡ G ( x ) − A ( x ) F(G(x))=\ln G(x)-A(x) F(G(x))=lnG(x)A(x)
要求 F ( G ( x ) ) F(G(x)) F(G(x))的零点,用牛顿迭代解方程。
G ( x ) = G 0 ( x ) − F ( G 0 ( x ) ) F ′ ( G 0 ( x ) ) G(x)=G_0(x)-\frac{F(G_0(x))}{F'(G_0(x))} G(x)=G0(x)F(G0(x))F(G0(x))
F ( G 0 ( x ) ) = ln ⁡ G 0 ( x ) − A ( x ) F(G_0(x))=\ln G_0(x)-A(x) F(G0(x))=lnG0(x)A(x)
F ′ ( G 0 ( x ) ) = 1 G 0 ( x ) F'(G_0(x))=\frac{1}{G_0(x)} F(G0(x))=G0(x)1
G ( x ) = G 0 ( x ) ( 1 − ln ⁡ G 0 ( x ) + A ( x ) ) G(x)=G_0(x)(1-\ln G_0(x)+A(x)) G(x)=G0(x)(1lnG0(x)+A(x))
A ( x ) B A(x)^B A(x)B
A ( x ) A(x) A(x)常数项为 1 1 1,则直接 ln ⁡ \ln ln然后 exp ⁡ \exp exp回来。
否则设 A ( x ) A(x) A(x)最低项为 a x b ax^b axb,先把 A A A除以 a x b ax^b axb,像上面那样做,最后乘回来就行。注意次数 m o d   p mod\ p mod p m o d   φ ( p ) mod\ \varphi(p) mod φ(p)的问题,另外判多项式全 0 0 0要注意一下次数不取模。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
using namespace std;
const int N=270005,mod=998244353,inv2=(mod+1)>>1;
int n,m,k,len,p,a[N],rev[N],inv[N],w[20][N],iw[20][N];
long long mx;
inline int add(int a,int b){
	a+=b;
	return a<mod?a:a-mod;
}
inline int dec(int a,int b){
	a-=b;
	return a<0?a+mod:a;
}
inline int mul(int a,int b){
	return 1LL*a*b%mod;
}
inline int fastpow(int a,int x){
	int res=1;
	while(x){	
		if(x&1){
			res=mul(res,a);
		}
		x>>=1;
		a=mul(a,a);
	}
	return res;
}
int rd(){
	char ch=getchar();
	int res=0;
	while(ch<'0'||ch>'9'){
		ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
		mx=max(mx,1LL*res*10+ch-'0');
		res=add(mul(res,10),ch-'0');
		p=(1LL*p*10+ch-'0')%(mod-1);
		ch=getchar();
	}
	return res;
}
void init(int len){
	inv[1]=1;
	for(int i=2;i<=len;i++){	
		inv[i]=mul(inv[mod%i],dec(mod,mod/i));
	}
	for(int i=1,t=0;i<len;i<<=1,t++){
		int wn=fastpow(3,(mod-1)/i/2),iwn=fastpow(wn,mod-2);
		for(int j=0;j<len;j+=(i<<1)){
			int w=1,iw=1;
			for(int k=j;k<j+i;k++,w=mul(w,wn),iw=mul(iw,iwn)){
				::w[t][k]=w;
				::iw[t][k]=iw;
			}
		}
	}
}
void ntt(int a[],int len){
	for(int i=0;i<len;i++){
		rev[i]=(rev[i>>1]>>1)|((i&1)*(len>>1));
		if(i<rev[i]){
			swap(a[i],a[rev[i]]);
		}
	}
	for(int i=1,t=0;i<len;i<<=1,t++){
		for(int j=0;j<len;j+=(i<<1)){
			int x,y;
			for(int k=j;k<j+i;k++){
				x=a[k];
				y=mul(w[t][k],a[k+i]);
				a[k]=add(x,y);
				a[k+i]=dec(x,y);
			}
		}
	}
}
void intt(int a[],int len){
	for(int i=0;i<len;i++){
		rev[i]=(rev[i>>1]>>1)|((i&1)*(len>>1));
		if(i<rev[i]){
			swap(a[i],a[rev[i]]);
		}
	}
	for(int i=1,t=0;i<len;i<<=1,t++){
		for(int j=0;j<len;j+=(i<<1)){
			int x,y;
			for(int k=j;k<j+i;k++){
				x=a[k];
				y=mul(iw[t][k],a[k+i]);
				a[k]=add(x,y);
				a[k+i]=dec(x,y);
			}
		}
	}
	for(int i=0;i<len;i++){
		a[i]=mul(a[i],inv[len]);
	}
}
void getinv(int a[],int res[],int len){
	static int b[N],c[N],d[N];
	for(int i=0;i<(len<<1);i++){
		b[i]=c[i]=d[i]=0;
	}
	b[0]=fastpow(a[0],mod-2);
	for(int i=2;i<=len;i<<=1){
		for(int j=0;j<i;j++){
			c[j]=b[j];
			d[j]=a[j];
		}
		ntt(c,i<<1);
		ntt(d,i<<1);
		for(int j=0;j<(i<<1);j++){
			c[j]=mul(c[j],dec(2,mul(c[j],d[j])));
		}
		intt(c,i<<1);
		for(int j=0;j<i;j++){
			b[j]=c[j];
		}
	}
	for(int i=0;i<len;i++){
		res[i]=b[i];
	}
}
int bsgs(int a,int b){
	static map<int,int> mp;
	mp.clear();
	int p=ceil(sqrt(mod)),s=1;
	for(int i=0;i<p;i++,s=mul(s,a)){
		mp[s]=i;
	}
	s=fastpow(s,mod-2);
	for(int i=0,j=b;i<mod;i+=p,j=mul(j,s)){
		if(mp.count(j)){
			return i+mp[j];
		}
	}
	return 0;
}
void getsqrt(int a[],int res[],int len){
	static int b[N],c[N],d[N];
	for(int i=0;i<(len<<1);i++){
		b[i]=c[i]=d[i]=0;
	}
	int tmp=fastpow(3,bsgs(3,a[0])>>1);
	tmp=min(tmp,mod-tmp);
	b[0]=tmp;
	for(int i=2;i<=len;i<<=1){
		for(int j=0;j<i;j++){
			c[j]=add(b[j],b[j]);
			d[j]=a[j];
		}
		getinv(c,c,i);
		ntt(c,i<<1);
		ntt(d,i<<1);
		for(int j=0;j<(i<<1);j++){
			c[j]=mul(c[j],d[j]);
		}
		intt(c,i<<1);
		for(int j=0;j<i;j++){
			b[j]=add(mul(b[j],inv2),c[j]);
		}
	}
	for(int i=0;i<len;i++){
		res[i]=b[i];
	}
}
void derivative(int a[],int res[],int len){
	static int b[N];
	for(int i=0;i<len-1;i++){
		b[i]=mul(i+1,a[i+1]);
	}
	b[len-1]=0;
	for(int i=0;i<len;i++){
		res[i]=b[i];
	}
}
void integral(int a[],int res[],int len){
	static int b[N];
	b[0]=0;
	for(int i=1;i<len;i++){
		b[i]=mul(a[i-1],inv[i]);
	}
	for(int i=0;i<len;i++){
		res[i]=b[i];
	}
}
void getln(int a[],int res[],int len){
	static int b[N],c[N];
	for(int i=0;i<(len<<1);i++){
		b[i]=c[i]=i<len?a[i]:0;
	}
	derivative(b,b,len);
	getinv(c,c,len);
	ntt(b,len<<1);
	ntt(c,len<<1);
	for(int i=0;i<(len<<1);i++){
		b[i]=mul(b[i],c[i]);
	}
	intt(b,len<<1);
	integral(b,res,len);
}
void getexp(int a[],int res[],int len){
	static int b[N],c[N],d[N];
	for(int i=0;i<(len<<1);i++){
		b[i]=c[i]=d[i]=0;
	}
	b[0]=1;
	for(int i=2;i<=len;i<<=1){
		for(int j=0;j<i;j++){
			c[j]=d[j]=b[j];
		}
		getln(c,c,i);
		for(int j=0;j<i;j++){
			c[j]=dec(a[j]+(j==0),c[j]);
		}
		ntt(c,i<<1);
		ntt(d,i<<1);
		for(int j=0;j<(i<<1);j++){
			c[j]=mul(c[j],d[j]);
		}
		intt(c,i<<1);
		for(int j=0;j<i;j++){
			b[j]=c[j];
		}
	}
	for(int i=0;i<len;i++){
		res[i]=b[i];
	}
}
int main(){
	scanf("%d",&n),k=rd();
	for(int i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	while(m<n&&!a[m]){
		m++;
	}
	if(m*mx>=n){
		for(int i=0;i<n;i++){
			printf("0 ");
		}
		return 0;
	}
	int tmp=fastpow(a[m],p),inv=fastpow(a[m],mod-2);
	for(int i=0;i<n;i++){
		a[i]=i<n-m?mul(a[i+m],inv):0;
	}
	for(len=1;len<n;len<<=1);
	init(len<<1);
	getln(a,a,len);
	for(int i=0;i<len;i++){
		a[i]=mul(a[i],k);
	}
	getexp(a,a,len);
	for(int i=0;i<n;i++){
		if(i<m*k){
			printf("0 ");
		}else{
			printf("%d ",mul(a[i-m*k],tmp));
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值