• 【学习笔记】多项式快速幂


    题目大意:

    [F(x)equiv A^k(x)(mod x^n) ]

    (F(x).)

    解法:

    首先我们直接(log k)次倍增求怎么想都有亿点慢。考虑推式子:

    [ln F(x)equiv kln A(x)(mod x^n) ]

    于是,先求(ln)(exp)回去就好惹qwq

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=998244353;
    const int N=310000;
    int rev[N],a[N],b[N],c[N],f[N],g[N];
    int n,G[N],e[N],k;
    int A[N],B[N],F[N]; 
    inline int add(int x,int y){return (x+y)%mod;}
    inline int mul(int x,int y){return 1ll*x*y%mod;}
    inline int read(){
    	int s=0,w=1;
    	char ch=getchar();
    	while(!isdigit(ch)){
    		if(ch=='-')w=-1;
    		ch=getchar();
    	}
    	while(isdigit(ch)){
    		s=s*10+ch-48;
    		ch=getchar();
    	}
    	return w==1?s:s;
    }
    inline int readMod(){
    	int s=0;
    	char ch=getchar();
    	while(!isdigit(ch)){
    		
    		ch=getchar();
    	}
    	while(isdigit(ch)){
    		s=mul(s,10);
    		s=add(s,ch);
    		s=add(s,mod-48);
    		ch=getchar();
    	}
    	return s;
    }
    inline int qpow(int a,int b){
    	int res=1;
    	while(b){
    		if(b&1)res=mul(res,a);
    		a=mul(a,a);b>>=1;
    	}
    	return res;
    }
    void NTT(int *a,int lim,int tp){
    	for(int i=0;i<lim;++i)if(i<rev[i])swap(a[i],a[rev[i]]);
    	for(int i=1;i<lim;i<<=1){
    		int gn=qpow(3,(mod-1)/(i<<1));
    		if(tp!=1)gn=qpow(gn,mod-2);
    		for(int j=0;j<lim;j+=(i<<1)){
    			int G=1;
    			for(int k=0;k<i;++k,G=mul(G,gn)){
    				int x=a[j+k],y=mul(G,a[i+j+k]);
    				a[j+k]=add(x,y);a[i+j+k]=add(x,mod-y);
    			}
    		}
    	}
    	if(tp==1)return;
    	int inv=qpow(lim,mod-2);
    	for(int i=0;i<lim;++i)a[i]=mul(a[i],inv); 
    }
    void Inv(int d,int *a,int *b){
    	if(d==1){b[0]=qpow(a[0],mod-2);return;}
    	Inv((d+1)>>1,a,b);
    	int lim=1,len=0;
    	while(lim<(d<<1))lim<<=1,len++;
    	for(int i=1;i<lim;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(len-1));
    	for(int i=0;i<d;++i)c[i]=a[i];
    	for(int i=d;i<lim;++i)c[i]=0;
    	NTT(c,lim,1);NTT(b,lim,1);
    	for(int i=0;i<lim;++i)b[i]=1ll*(2-1ll*b[i]*c[i]%mod+mod)%mod*b[i]%mod;
    	NTT(b,lim,-1);for(int i=d;i<lim;++i)b[i]=0;
    }
    inline void Dx(int *a,int *b,int L){
    	for(int i=1;i<L;++i)b[i-1]=mul(a[i],i);
    	b[L-1]=0;
    }
    inline void Int(int *a,int *b,int L){
    	for(int i=1;i<L;++i)b[i]=mul(a[i-1],qpow(i,mod-2));
    	b[0]=0;
    }
    void Ln(int L,int *a,int *R){
    	Dx(a,e,L);Inv(L,a,f);
    	int lim=1,len=0;
    	while(lim<(L<<1))lim<<=1,len++;
    	for(int i=1;i<lim;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(len-1));
    	NTT(e,lim,1);NTT(f,lim,1);
    	for(int i=0;i<lim;++i)e[i]=mul(e[i],f[i]);
    	NTT(e,lim,-1);Int(e,R,lim);
    	for(int i=0;i<lim;++i)e[i]=f[i]=0;
    }
    void Exp(int d,int *a,int *b){
    	if(d==1){b[0]=1;return;}
    	Exp((d+1)>>1,a,b);
    	Ln(d,b,G);
    	int lim=1,len=0;
    	while(lim<(d<<1))lim<<=1,len++;
    	for(int i=1;i<lim;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(len-1));
    	for(int i=0;i<d;++i)G[i]=a[i]>=G[i]?a[i]-G[i]:a[i]-G[i]+mod;
    	for(int i=d;i<lim;++i)b[i]=G[i]=0;
    	G[0]++;NTT(G,lim,1);NTT(b,lim,1);
    	for(int i=0;i<lim;++i)b[i]=mul(b[i],G[i]);
    	NTT(b,lim,-1);
    	for(int i=d;i<lim;++i)b[i]=G[i]=0;
    }
    int main(){
    	n=read();k=readMod();
    	for(int i=0;i<n;++i)a[i]=read();
    	int len=1;for(;len<=n;len<<=1);
    	Ln(len,a,A);
    	for(int i=0;i<len;++i)A[i]=mul(A[i],k);
    	Exp(len,A,B);
    	for(int i=0;i<n;++i)printf("%d ",B[i]);
    	return 0;
    } 
    
  • 相关阅读:
    SQL Server 损坏修复
    记录一些数据库函数或全局变量
    查询数据库空间使用情况
    SQL Server 2008文件与文件组的关系
    大型网站--负载均衡架构
    本地事务和分布式事务工作实践
    IIS防止同一IP大量非法访问
    使用EventLog类写Windows事件日志
    1878: [SDOI2009]HH的项链
    模板
  • 原文地址:https://www.cnblogs.com/h-lka/p/14496410.html
Copyright © 2020-2023  润新知