zoukankan      html  css  js  c++  java
  • 多项式重工业基地

    未完待续……(只是给自己存个板子)

    快速傅里叶变换

    #include <bits/stdc++.h>
    
    using namespace std; const int maxn = 2e6 + 1e2;
    
    struct Cp
    {
    	double x, y;
    
    	inline Cp operator +(const Cp& b) const { return (Cp) { x + b.x, y + b.y }; }
    
    	inline Cp operator -(const Cp& b) const { return (Cp) { x - b.x, y - b.y }; }
    
    	inline Cp operator *(const Cp& b) const { return (Cp) { x * b.x - y * b.y, x * b.y + y * b.x }; }
    };
    
    namespace fft
    {
    	int l, r[maxn], lim = 1; long double Pi = acos(-1.0); inline void init(int n)
    	{
    		while (lim <= n) lim <<= 1, l++; for (int i = 0; i < lim; i++)
    		{
    			r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
    		}
    	}
    
    	inline void fft(Cp A[], int v)
    	{
    		for (int i = 0; i < lim; i++) if (i < r[i]) swap(A[i], A[r[i]]);
    		
    		Cp Wn, w, x, y; for (int mid = 1; mid < lim; mid <<= 1)
    		{
    			Wn = (Cp) { cos(Pi / mid), v * sin(Pi / mid) }; for (int R = mid << 1, j = 0; j < lim; j += R)
    			{
    				w = (Cp) { 1, 0 }; for (int k = 0; k < mid; k++, w = w * Wn)
    				{
    					x = A[j + k], y = w * A[j + mid + k], A[j + k] = x + y, A[j + mid + k] = x - y;
    				}
    			}
    		}
    		for (int i = 0; i < lim; i++) (v > 0) ? (A[i].x /= lim, A[i].y /= lim) : (A[i].x *= lim, A[i].y /= lim);
    	}
    
    	inline void conv(Cp A[], Cp B[], Cp C[]) { for (int i = 0; i < lim; i++) C[i] = A[i] * B[i]; }
    }
    
    Cp A[maxn], B[maxn], C[maxn]; int n, m; int main()
    {
    	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0), cin >> n >> m;
    	for (int i = 0; i <= n; i++) cin >> A[i].x;
    	for (int i = 0; i <= m; i++) cin >> B[i].x;
    	fft::init(n + m), fft::fft(A, 1), fft::fft(B, 1), fft::conv(A, B, C), fft::fft(C, -1);
    	for (int i = 0; i <= n + m; i++) cout << int(C[i].x + 0.5) << ' '; return 0;
    	
    }
    

    快速数论变换:

    
    #include <bits/stdc++.h>
    
    using namespace std; const int maxn = 5e5 + 1e2, mod = 998244353, g = 3, h = 332748118;
    
    namespace fft
    {
    	int l, r[maxn], lim = 1; inline void init(int n)
    	{
    		while (lim <= n) lim <<= 1, l++; for (int i = 0; i < lim; i++)
    		{
    			r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
    		}
    	}
    
    	inline int fpow(int x, int k)
    	{
    		int res = 1; while (k) { if (k & 1) res = 1ll * res * x % mod; x = 1ll * x * x % mod; k >>= 1; } return res;
    	}
    
    	inline void fft(int A[], int v)
    	{
    		for (int i = 0; i < lim; i++) if (i < r[i]) swap(A[i], A[r[i]]);
    		
    		int Wn, w, x, y; for (int mid = 1; mid < lim; mid <<= 1)
    		{
    			Wn = fpow(v == 1 ? g : h, (mod - 1) / (mid << 1)); for (int R = mid << 1, j = 0; j < lim; j += R)
    			{
    				w = 1; for (int k = 0; k < mid; k++, w = 1ll * w * Wn % mod)
    				{
    					y = 1ll * w * A[j + mid + k] % mod, A[j + mid + k] = (A[j + k] - y) % mod, A[j + k] = (A[j + k] + y) % mod;
    				}
    			}
    		}
    		int inv = fpow(lim, mod - 2);
    		for (int i = 0; i < lim; i++) (v > 0) ? (A[i] = A[i] * 1ll * inv % mod) : (A[i] = A[i] * 1ll * lim % mod);
    	}
    
    	inline void conv(int A[], int B[], int C[]) { for (int i = 0; i < lim; i++) C[i] = 1ll * A[i] * B[i] % mod; }
    }
    
    int A[maxn], B[maxn], C[maxn]; int n, m; int main()
    {
    	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0), cin >> n >> m;
    	for (int i = 0; i <= n; i++) cin >> A[i];
    	for (int i = 0; i <= m; i++) cin >> B[i];
    	fft::init(n + m), fft::fft(A, 1), fft::fft(B, 1), fft::conv(A, B, C), fft::fft(C, -1);
    	for (int i = 0; i <= n + m; i++) cout << (C[i] + mod) % mod << ' '; return 0;
    	
    }
    

    快速莫比乌斯/沃尔什变换:

    namespace fwt
    
    {
    	int lim; inline void init(int n) { lim = 1; while (lim < n) lim <<= 1; }
    
    	inline void OR(modint f[], modint t)
    	{
    		for (int mid = 1; mid < lim; mid <<= 1) for (int R = (mid << 1), j = 0; j < lim; j += R)
    			for (int k = 0; k < mid; k++) f[j + k + mid] += f[j + k] * t;
    	}
    
    	inline void AND(modint f[], modint t)
    	{
    		for (int mid = 1; mid < lim; mid <<= 1) for (int R = (mid << 1), j = 0; j < lim; j += R)
    			for (int k = 0; k < mid; k++) f[j + k] += f[j + k + mid] * t;
    	}
    
    	inline void XOR(modint f[], modint t)
    	{
    		for (int mid = 1; mid < lim; mid <<= 1) for (int R = (mid << 1), j = 0; j < lim; j += R)
    			for (int k = 0; k < mid; k++)
    			{
    				f[j + k] += f[j + mid + k], f[j + mid + k] = f[j + k] - f[j + mid + k] - f[j + mid + k], f[j + k] *= t, f[j + mid + k] *= t;
    			}
    	}
    
    	inline void CONV(modint A[], modint B[], modint C[]) { for (int i = 0; i < lim; i++) C[i] = A[i] * B[i]; }
    }
    

    modint 类(乱入):

    int ttmp; struct modint
    
    {
    	int x; modint(int o) { x = o; } modint() { x = 0; }
    
    	inline modint &operator =(int o) { return x = o, *this; }
    
    	inline modint &operator +=(modint b) { return x = (ttmp = x + b.x) >= mod ? ttmp - mod : ttmp, *this; }
    
    	inline modint &operator -=(modint b) { return x = (ttmp = x - b.x) < 0 ? ttmp + mod : ttmp, *this; }
    
    	inline modint &operator *=(modint b) { return x = 1ll * x * b.x % mod, *this; }
    
    	inline modint operator ^(int k)
    	{
    		modint res = 1, xx = x; while (k) { if (k & 1) res *= xx; k >>= 1, xx = xx * xx; } return res;
    	}
    
    	inline modint operator /=(modint b) { return x = 1ll * x * ((b ^ (mod - 2)).x) % mod, *this; }
    
    	inline modint operator /=(int b) { return x = 1ll * x * (modint(b) ^ (mod - 2)).x, *this; }
    
    	inline modint operator +(modint b) const { return modint((ttmp = x + b.x) >= mod ? ttmp - mod : ttmp); }
    
    	inline modint operator -(modint b) const { return modint((ttmp = x - b.x) < 0 ? ttmp + mod : ttmp); }
    
    	inline modint operator *(modint b) const { return modint(1ll * x * b.x % mod); }
    
    	inline modint operator /(modint b) const { return modint(1ll * x * ((b ^ (mod - 2)).x) % mod); }
    };
    

    多项式乘法逆:

    #include <bits/stdc++.h>
    
    using namespace std; const int maxn = 1e6 + 1e2, mod = 998244353, G = 3, gi = 332748118;
    
    namespace ntt
    {
    	int lim, l, r[maxn]; inline void init(int n)
    	{
    		lim = 1, l = 0; while (lim <= n) lim <<= 1, l++; for (int i = 0; i < lim; i++)
    		{
    			r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
    		}
    	}
    
    	inline int qpow(int x, int k)
    	{
    		int res = 1; while (k) { if (k & 1) res = 1ll * res * x % mod; x = 1ll * x * x % mod, k >>= 1; } return res;
    	}
    
    	inline void ntt(int A[], int type)
    	{
    		for (int i = 0; i < lim; i++) if (i < r[i]) swap(A[i], A[r[i]]);
    
    		int Wn, w, y, mid, j, k, R; for (mid = 1; mid < lim; mid <<= 1)
    		{
    			Wn = qpow(type == 1 ? G : gi, (mod - 1) / (mid << 1)); for (j = 0, R = (mid << 1); j < lim; j += R)
    			{
    				w = 1; for (k = 0; k < mid; k++, w = 1ll * w * Wn % mod)
    				{
    					y = A[j + k + mid] * 1ll * w % mod, A[j + k + mid] = (A[j + k] - y) % mod, A[j + k] = (A[j + k] + y) % mod;
    				}
    			}
    		}
    		int inv = qpow(lim, mod - 2);
    		for (int i = 0; i < lim; i++) (type == 1) ? (A[i] = A[i] * 1ll * inv % mod) : (A[i] = A[i] * 1ll * lim % mod);
    	}
    
    	int A[maxn], B[maxn]; inline void conv(int a[], int b[], int C[], int n, int m, int k)
    	{
    		for (int i = 0; i <= n; i++) A[i] = a[i];
    		for (int i = 0; i <= m; i++) B[i] = b[i];
    		init(n + m), ntt(A, 1), ntt(B, 1); for (int i = 0; i < lim; i++) C[i] = 1ll * A[i] * B[i] % mod;
    		ntt(C, mod - 1); for (int i = k; i < lim; i++) C[i] = 0;
    		for (int i = 0; i < lim; i++) A[i] = B[i] = 0;
    	}
    }
    
    
    int t[maxn]; inline void PolyInv(int f[], int g[], int n)
    {
    	if (n == 1) { g[0] = ntt::qpow(f[0], mod - 2); return; }
    	int m = (n + 1) >> 1; PolyInv(f, g, m);
    	ntt::conv(f, g, t, n - 1, m - 1, n);
    	for (int i = 0; i < n; i++) t[i] = -t[i]; t[0] += 2;
    	ntt::conv(g, t, g, m - 1, n - 1, n);
    }
    
    int f[maxn], g[maxn], n;
    
    int main()
    {
    	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0), cin >> n;
    	for (int i = 0; i < n; i++) cin >> f[i]; PolyInv(f, g, n);
    	for (int i = 0; i < n; i++) cout << (g[i] + mod) % mod << ' '; return 0;
    }
    

    多项式开根(接在逆元的后面):

    int u[maxn]; inline void PolySqrt(int f[], int g[], int n)
    {
    	if (n == 1) { g[0] = 1; return; }
    	int m = (n + 1) >> 1; PolySqrt(f, g, m);
    	PolyInv(g, u, n), ntt::conv(u, f, u, n - 1, n - 1, n);
    	int inv = ntt::qpow(2, mod - 2);
    	for (int i = 0; i < n; i++) g[i] = (g[i] + u[i]) * 1ll * inv % mod;
    }
    

    子集卷积:

    #include <bits/stdc++.h>
    
    using namespace std; const int maxn = 1 << 22, mod = 1e9 + 9;
    
    inline void fwt(int f[], int n, int t)
    {
    	for (int mid = 1; mid < (1 << n); mid <<= 1) for (int j = 0, R = (mid << 1); j < (1 << n); j += R)
    		for (int k = 0; k < mid; k++) (f[j + k + mid] += f[j + k] * t) %= mod;
    }
    
    int n, a[21][maxn], b[21][maxn], c[21][maxn], t[maxn];
    
    int main()
    {
    	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0), cin >> n;
    	for (int i = 0; i < (1 << n); i++) cin >> a[__builtin_popcount(i)][i];
    	for (int i = 0; i < (1 << n); i++) cin >> b[__builtin_popcount(i)][i];
    	for (int i = 0; i <= n; i++) fwt(a[i], n, 1), fwt(b[i], n, 1);
    	for (int i = 0; i <= n; i++) for (int j = 0; j <= n - i; j++)
    	{
    		for (int k = 0; k < (1 << n); k++) (c[i + j][k] += a[i][k] * 1l * b[j][k] % mod) %= mod;
    	}
    	for (int i = 0; i <= n; i++) fwt(c[i], n, -1);
    	for (int i = 0; i < (1 << n); i++) cout << (c[__builtin_popcount(i)][i] + mod) % mod << ' ';
    }
    

    Ln & Exp 指数 / 对数函数

    int v[maxn]; inline void PolyLn(int f[], int g[], int n)
    
    {
    	PolyInv(f, g, n); for (int i = 1; i < n; i++) v[i - 1] = f[i] * 1ll * i % mod;
           	ntt::conv(v, g, g, n - 2, n - 1, n);
    	for (int i = n - 1; i; i--) g[i] = g[i - 1] * 1ll * ntt::qpow(i, mod - 2) % mod; g[0] = 0;
    }
    
    int w[maxn]; inline void PolyExp(int f[], int g[], int n)
    {
    	if (n == 1) { g[0] = 1; return ; }
    	int m = (n + 1) >> 1; PolyExp(f, g, m);
    	PolyLn(g, w, n); for (int i = 0; i < n; i++) w[i] = (- w[i] + f[i]) % mod; w[0]++;
    	ntt::conv(w, g, g, n - 1, m - 1, n);
    }
    

    未完待续……敬请期待(bushi

    as 0.4123
  • 相关阅读:
    bzoj1066: [SCOI2007]蜥蜴
    bzoj3504: [Cqoi2014]危桥
    bzoj2756: [SCOI2012]奇怪的游戏
    bzoj1570: [JSOI2008]Blue Mary的旅行
    Ultra-QuickSort
    Bin Packing
    Watering Grass
    区间覆盖
    抄书 Copying Books UVa 714
    分馅饼 Pie
  • 原文地址:https://www.cnblogs.com/Linshey/p/14400905.html
Copyright © 2011-2022 走看看