• 多项式全家桶


    相关知识以后补,先存份代码。

    #include <set>
    #include <map>
    #include <queue>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define pii pair <int , int>
    #define mp make_pair
    #define fs first
    #define sc second
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    
    
    //const int Mxdt=100000; 
    //static char buf[Mxdt],*p1=buf,*p2=buf;
    //#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,Mxdt,stdin),p1==p2)?EOF:*p1++;
    template <typename T>
    void read(T &x) {
    	x=0;T f=1;char s=getchar();
    	while(s<'0'||s>'9') {if(s=='-') f=-1;s=getchar();}
    	while(s>='0'&&s<='9') {x=(x<<3)+(x<<1)+(s^'0');s=getchar();}
    	x *= f;
    }
    
    template <typename T>
    void write(T x , char s='\n') {
    	if(x<0) {putchar('-');x=-x;}
    	if(!x) {putchar('0');putchar(s);return;}
    	T tmp[25] = {} , t = 0;
    	while(x) tmp[t ++] = x % 10 , x /= 10;
    	while(t -- > 0) putchar(tmp[t] + '0');
    	putchar(s);
    }
    
    const int MAXN = 2e6 + 5;
    const int mod = 998244353;
    
    inline int Add(int x , int y) {x += y;return x >= mod?x - mod:x;}
    inline int Sub(int x , int y) {x -= y;return x < 0?x + mod:x;}
    inline int Mul(int x , int y) {return 1ll * x * y % mod;}
    
    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;
    }
    
    inline int Cipolla(int n , int mod) {
    	if(!n) return 0;
    	if(qpow(n , (mod - 1) / 2) != 1) return -1;
    	int a = 1;
    	while(1) {
    		a = rand() % mod;
    		if(a && qpow(Sub(Mul(a , a) , n) , (mod - 1) / 2) != 1) break; 
    	}
    	const int I_P = Sub(Mul(a , a) , n);
    	pii A = mp(a , 1) , res = mp(1 , 0);
    	int b = (mod + 1) / 2;
    	while(b) {
    		if(b & 1) {
    			pii tmp;
    			tmp.fs = Add(Mul(res.fs , A.fs) , Mul(I_P , Mul(res.sc , A.sc)));
    			tmp.sc = Add(Mul(res.fs , A.sc) , Mul(res.sc , A.fs));
    			res = tmp;
    		}
    		pii tmp;
    		tmp.fs = Add(Mul(A.fs , A.fs) , Mul(I_P , Mul(A.sc , A.sc)));
    		tmp.sc = Add(Mul(A.fs , A.sc) , Mul(A.sc , A.fs));
    		A = tmp;
    		b >>= 1;
    	}
    	int x = res.fs , y = Sub(0 , x); 
    	return min(x , y);
    }
    
    namespace Poly_Family {
    	#define poly vector <int> 
    	#define Len(x) (int)x.size()
    	
    	int r[MAXN << 2];
    	poly w[2][23];
    	
    	inline void pre(int op) {
    		for (int t = 1; t <= 22; ++t) {
    			w[op][t].resize(1 << t);
    			int k = (1 << (t - 1));
    			int ori = qpow(3 , (op == 1)?(mod - 1) / (k << 1):(mod - 1) - (mod - 1) / (k << 1));
    			int now = 1;
    			for (int j = 0; j < k; ++j) {
    				w[op][t][j] = now;
    				now = Mul(now , ori);
    			}
    		}
    	}
    	
    	inline void Resize(poly &F , int n) {F.resize(n , 0);}
    	
    	inline void NTT(poly &F , int op) {
    		if(op == -1) op = 0;
    		int N = Len(F);
    		for (int i = 0; i < N; ++i) if(i < r[i]) swap(F[i] , F[r[i]]);
    		for (int k = 1 , t = 1; k < N; k <<= 1 , t ++) {
    			for (int i = 0; i < (N >> t); ++i) {
    				for (int j = 0; j < k; ++j) {
    					int cur = Mul(w[op][t][j] , F[(i << t) ^ k ^ j]);
    					F[(i << t) ^ j ^ k] = Sub(F[(i << t) ^ j] , cur);
    					F[(i << t) ^ j] = Add(F[(i << t) ^ j] , cur);
    				}
    			}
    		} 
    		if(op == 0) {
    			int D = qpow(N , mod - 2);
    			for (int i = 0; i < N; ++i) F[i] = Mul(F[i] , D);
    		}
    	}
    	
    	inline poly operator - (poly F , poly G) {
    		int n = Len(F) , m = Len(G) , N = max(n , m);
    		Resize(F , N) , Resize(G , N);
    		for (int i = 0; i < Len(F); ++i) F[i] = Sub(F[i] , G[i]) % mod;
    		return F;
    	}
    
    	inline poly operator + (poly F , poly G) {
    		int n = Len(F) , m = Len(G) , N = max(n , m);
    		Resize(F , N) , Resize(G , N);
    		for (int i = 0; i < Len(F); ++i) F[i] = Add(F[i] , G[i]) % mod;
    		return F;
    	}
    	
    	inline poly operator * (poly F , poly G) {
    		poly FG;
    		int n = Len(F) , m = Len(G) , rl = n + m - 1 , N = 1;
    		while(N < rl) N <<= 1;
    		Resize(F , N) , Resize(G , N) , Resize(FG , N);
    		for (int i = 1; i < N; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1)?(N >> 1):0);
    		NTT(F , 1) , NTT(G , 1);
    		for (int i = 0; i < N; ++i) FG[i] = Mul(F[i] , G[i]);
    		NTT(FG , -1);
    		Resize(FG , rl);
    		return FG;
    	}
    	
    	inline poly Deri(poly F) {
    		for (int i = 0; i < Len(F) - 1; ++i) F[i] = Mul(F[i + 1] , i + 1);
    		F[Len(F) - 1] = 0;
    		return F;
    	}
    	
    	inline poly Integ(poly F) {
    		Resize(F , Len(F) + 1);
    		for (int i = Len(F) - 1; i >= 1; --i) F[i] = Mul(F[i - 1] , qpow(i , mod - 2));
    		F[0] = 0;
    		return F;
    	}
    	
    	inline poly Inv(poly F) {
    		poly G;
    		G.resize(1);
    		G[0] = qpow(F[0] , mod - 2);
    		for (int k = 2; k <= 2 * Len(F); k <<= 1) {
    			poly A = F;
    			Resize(A , k);
    			
    			Resize(G , k);
    			for (int i = 1; i < k; ++i) r[i] = (r[i >> 1] >> 1) | ((i & 1)?(k >> 1):0);
    			
    			NTT(G , 1);
    			poly tmp;Resize(tmp , k);
    			for (int i = 0; i < Len(G); ++i) tmp[i] = Mul(G[i] , G[i]);
    			NTT(tmp , -1) , NTT(G , -1);
    			tmp = tmp * A;
    			Resize(tmp , k);
    			for (int i = 0; i < Len(G); ++i) G[i] = Mul(G[i] , 2);
    			G = G - tmp;
    		}
    		return G;
    	}
    	
    	inline poly operator / (poly F , poly G) {
    		reverse(F.begin() , F.end());
    		reverse(G.begin() , G.end());
    		int n = Len(F) , m = Len(G);
    		int N = n - m + 1;
    		Resize(G , N);
    		G = Inv(G);
    		poly Q = F * G;Resize(Q , N);
    		reverse(Q.begin() , Q.end());
    		return Q;
    	}
    	
    	inline poly Ln(poly F) {
    		poly G = Integ(Inv(F) * Deri(F));
    		return G;
    	}
    	
    	inline poly Exp(poly F) {
    		poly f;Resize(f , 1);
    		f[0] = 1;
    		for (int k = 2; k <= 2 * Len(F); k <<= 1) {
    			poly A = F;
    			Resize(A , k);
    			A = A - Ln(f);
    			A[0] = Add(A[0] , 1);
    			f = f * A;
    			Resize(f , k);
    		}
    		return f;
    	}
    	
    	inline poly Qpow(poly F , int k1 , int k2 , int p) {
    		int l = -1;
    		for (int i = 0; i < Len(F); ++i) if(F[i]) {
    			l = i;
    			break;
    		}
    		if(l == -1) return F;
    		if((LL)l * k1 + p * mod * (l > 0) >= Len(F)) {
    			for (int i = 0; i < Len(F); ++i) F[i] = 0;
    			return F;
    		}
    		poly G;G.resize(Len(F) - l);
    		for (int i = 0; i < Len(G); ++i) G[i] = F[i + l];
    		int v = G[0] , iv = qpow(v , mod - 2);
    		for (int i = 0; i < Len(G); ++i) G[i] = Mul(G[i] , iv); 
    		
    		G = Ln(G),Resize(G , Len(F) - l);
    		for (int i = 0; i < Len(G); ++i) G[i] = Mul(G[i] , k1);
    		G = Exp(G),Resize(G , Len(F) - l);
    		
    		v = qpow(v , k2);
    		for (int i = 0; i < Len(G); ++i) G[i] = Mul(G[i] , v);
    		
    		l *= k1;
    		for (int i = 0; i < l; ++i) F[i] = 0;
    		for (int i = l; i < Len(F); ++i) F[i] = G[i - l]; 
    		
    		return F;
    	}
    	
    	inline poly Sqrt(poly F) {
    		poly f;Resize(f , 1);
    		f[0] = Cipolla(F[0] , mod);
    		if(f[0] == -1) return f;
    		int inv2 = (mod + 1) >> 1;
    		for (int k = 2; k <= 2 * Len(F); k <<= 1) {
    			poly A = F;
    			Resize(A , k);
    			poly tmp = Inv(f);
    			Resize(tmp , k);
    			f = f + tmp * A;
    			Resize(f , k);
    			for (int i = 0; i < Len(f); ++i) f[i] = Mul(f[i] , inv2);
    			Resize(f , k);
    		}
    		return f;
    	}
    }
    
    using namespace Poly_Family;
    
    poly F;
    int n;
    
    int main() {
    	pre(0) , pre(1);
    	int n , k1 = 0 , k2 = 0 , p = 0;
    	read(n);
    	
    	char s=getchar();
    	while(s<'0'||s>'9') s=getchar();
    	while(s>='0'&&s<='9') {p |= (k1 * 10ll + (s ^ '0') >= mod) , k1 = Add(Mul(k1 , 10) , s ^ '0') , k2 = (k2 * 10ll % (mod - 1) + (s ^ '0')) % (mod - 1);s=getchar();}
    	
    	Resize(F , n);
    	for (int i = 0; i < n; ++i) read(F[i]);
    	
    	F = Qpow(F , k1 , k2 , p);
    	
    	for (int i = 0; i < Len(F); ++i) write(F[i] , (i!=Len(F))?' ':'\n');
    	return 0;
    }
    
  • 相关阅读:
    共享内存:mmap函数实现
    navigationItem.rightBarButtonItem 设置背景图片,颜色更改解决的方法
    C语言基础
    easyui datagrid合并相同数据的单元格。
    js 计算总页数的最高效方式
    取消本地文件夹与SVN服务器的关联
    扩展自easyui的combo组件的下拉多选控件
    利用art.template模仿VUE 一次渲染多个模版
    利用art.template模仿VUE
    JavaScript单独的模块中传递数据
  • 原文地址:https://www.cnblogs.com/Reanap/p/16230500.html
Copyright © 2020-2023  润新知