板子集

数学

多项式

FWT

#include<bits/stdc++.h>
#define mod 998244353
#define ll long long
using namespace std;
const int N = (1 << 17) + 5;
void fwt_or(ll *a, int len, int opt){
	for(int i = 2; i <= len; i <<= 1)
		for(int p = i >> 1, j = 0; j + i <= len; j += i)
			for(int k = j; k < j + p; k ++)
				a[p + k] =(a[p + k] + opt * a[k] + mod) % mod;
}
void fwt_and(ll *a, int len, int opt){
	for(int i = 2; i <= len; i <<= 1)
		for(int p = i >> 1, j = 0; j + i <= len; j += i)
			for(int k = j; k < j + p; k ++)
				a[k] = (a[k] + opt * a[k + p] + mod) % mod;
}
 
void fwt_xor(ll *a, int len, int opt){
	for(int i = 2; i <= len; i <<= 1)
		for(int p = i >> 1, j = 0; j + i <= len; j += i)
			for(int k = j; k < j + p; k ++){
				int X = a[k], Y = a[k + p];
				a[k] = (X + Y) % mod, a[k + p] = (X - Y + mod) % mod;
				if(opt == -1) a[k] = a[k] * 499122177 % mod, a[k + p] = a[k + p] * 499122177 % mod;
			}
				
}

int n;
ll a[N], b[N], f[N], g[N];
int main(){
	scanf("%d", &n);
	int len = (1 << n);
	for(int i = 0; i < len; i ++) scanf("%lld", &a[i]);
	for(int i = 0; i < len; i ++) scanf("%lld", &b[i]);
	
	for(int i = 0; i < len; i ++) f[i] = a[i], g[i] = b[i];
	fwt_or(f, len, 1), fwt_or(g, len, 1);
	for(int i = 0; i < len; i ++) f[i] = f[i] * g[i] % mod;
	fwt_or(f, len, -1);
	for(int i = 0; i < len; i ++) printf("%lld ", f[i]); printf("\n");
	
	for(int i = 0; i < len; i ++) f[i] = a[i], g[i] = b[i];
	fwt_and(f, len, 1), fwt_and(g, len, 1);
	for(int i = 0; i < len; i ++) f[i] = f[i] * g[i] % mod;
	fwt_and(f, len, -1);
	for(int i = 0; i < len; i ++) printf("%lld ", f[i]); printf("\n");
	
	for(int i = 0; i < len; i ++) f[i] = a[i], g[i] = b[i];
	fwt_xor(f, len, 1), fwt_xor(g, len, 1);
	for(int i = 0; i < len; i ++) f[i] = f[i] * g[i] % mod;
	fwt_xor(f, len, -1);
	for(int i = 0; i < len; i ++) printf("%lld ", f[i]); printf("\n");
	
	
	return 0;
}


FFT

#include<bits/stdc++.h>
#define N (1<<22) 
using namespace std;
const double pi = acos(-1);
const double eps = 0.49;
struct cp{
	double x, y;
	cp(double xx = 0, double yy = 0) {x = xx, y = yy;}
}a[N], b[N], w0[N];
cp operator +(cp a, cp b) {return cp(a.x + b.x, a.y + b.y);}
cp operator -(cp a, cp b) {return cp(a.x - b.x, a.y - b.y);}
cp operator *(cp a, cp b) {return cp(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);}
int n, m, rev[N];
void fft(cp *a, int len, int o){
	for(int i = 0; i <= len; i ++) if(i < rev[i]) swap(a[i], a[rev[i]]);
	for(int i = 2; i <= len; i <<= 1){
		cp wn = cp(cos(pi * 2 / i), o * sin(pi * 2 / i));
		w0[0] = cp(1, 0);
		for(int j = 1; j <= i / 2; j ++) w0[j] = w0[j - 1] * wn;//预处理单位根
		for(int j = 0, p = i / 2; j + i - 1 <= len; j += i){
			for(int k = j; k < j + p; k ++){ 
				cp X = a[k], Y = w0[k - j] * a[k + p];
				a[k] = X + Y;
				a[k + p] = X - Y;
			}
		}
	}
		
}

int main(){
	scanf("%d%d", &n, &m);
	for(int i = 0; i <= n; i ++) scanf("%lf", &a[i].x);
	for(int i = 0; i <= m; i ++) scanf("%lf", &b[i].x);
	int len = 1;
	for(;len <= n + m; len <<= 1);
	for(int i = 1; i <= len; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1)? len >> 1:0);
	fft(a, len, 1), fft(b, len, 1);
	for(int i = 0; i <= len; i ++) a[i] = a[i] * b[i];
	fft(a, len, -1);
	for(int i = 0; i <= n + m; i ++) printf("%d ", (int)(a[i].x / len + eps));
	return 0;
}

NTT

#include<bits/stdc++.h>
#define mod 998244353	
#define G 3
#define N 8000005
#define int long long
using namespace std;
int qpow(int x, int y){
	int ret = 1;
	for(; y; y >>= 1, x = x * x % mod) if(y & 1) ret = ret * x % mod;
	return ret;
}
int rev[N], G_inv, len_inv;
void ntt(int *a, int len, int o){
	for(int i = 1; i <= len; i ++) if(i < rev[i]) swap(a[i], a[rev[i]]);
	for(int i = 2; i <= len; i <<= 1){
		int wn = qpow((o == 1)? G:G_inv, (mod - 1) / i);
		for(int j = 0, p = i / 2; j + i - 1 <= len; j += i){
			int w0 = 1;
			for(int k = j; k < j + p; k ++, w0 = w0 * wn % mod){
				int X = a[k], Y = w0 * a[k + p] % mod;
				a[k] = (X + Y) % mod;
				a[k + p] = (X - Y + mod) % mod;
			}
		}
	}
}
int n, m, a[N], b[N];
signed main(){
	scanf("%lld%lld", &n, &m);
	for(int i = 0; i <= n; i ++) scanf("%lld", &a[i]);
	for(int i = 0; i <= m; i ++) scanf("%lld", &b[i]);
	int len = 1;
	for(; len <= n + m; len <<= 1);
	len_inv = qpow(len, mod - 2), G_inv = qpow(G, mod - 2);
	for(int i = 1; i <= len; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i&1) * len>>1);
	ntt(a, len, 1), ntt(b, len, 1);
	for(int i = 0; i <= len; i ++) a[i] = a[i] * b[i] % mod;
	ntt(a, len, -1);
	for(int i = 0; i <= n + m; i ++) printf("%lld ", a[i] * len_inv % mod);
	return 0;
}

多项式求逆

#include<bits/stdc++.h>
#define mod 998244353	
#define G 3
#define N 8000005
#define int long long
using namespace std;
int qpow(int x, int y){
	int ret = 1;
	for(; y; y >>= 1, x = x * x % mod) if(y & 1) ret = ret * x % mod;
	return ret;
}
int rev[N], G_inv, len_inv;
void ntt(int *a, int len, int o){
	for(int i = 1; i <= len; i ++) if(i < rev[i]) swap(a[i], a[rev[i]]);
	for(int i = 2; i <= len; i <<= 1){
		int wn = qpow((o == 1)? G:G_inv, (mod - 1) / i);
		for(int j = 0, p = i / 2; j + i - 1 <= len; j += i){
			int w0 = 1;
			for(int k = j; k < j + p; k ++, w0 = w0 * wn % mod){
				int X = a[k], Y = w0 * a[k + p] % mod;
				a[k] = (X + Y) % mod;
				a[k + p] = (X - Y + mod) % mod;
			}
		}
	}
}
int c[N];
void work(int *a, int *b, int sz){
	if(sz == 1) {b[0] = qpow(a[0], mod - 2); return;}
	work(a, b, (sz + 1) / 2);
	int len = 1;
	for(; len < sz + sz; len <<= 1);
	len_inv = qpow(len, mod - 2), G_inv = qpow(G, mod - 2);
	for(int i = 0; i <= len; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i&1) * len>>1), c[i] = a[i];
	for(int i = sz; i <= len; i ++) c[i] = 0;
	ntt(c, len, 1), ntt(b, len, 1);
	for(int i = 0; i <= len; i ++) b[i] = (2ll * b[i] % mod - c[i] * b[i] % mod * b[i] % mod + mod) % mod;
	ntt(b, len, -1);
	for(int i = 0; i <= len; i ++) b[i] = b[i] * len_inv % mod;
	for(int i = sz; i <= len; i ++) b[i] = 0;
}
int n, m, a[N], b[N];
signed main(){
	scanf("%lld", &n);
	for(int i = 0; i < n; i ++) scanf("%lld", &a[i]);	
	work(a, b, n);
	for(int i = 0; i < n; i ++) printf("%lld ", b[i]);
	return 0;
}

分治FFT(假,这是求逆)


#include<bits/stdc++.h>
#define mod 998244353	
#define G 3
#define N 8000005
#define int long long
using namespace std;
int qpow(int x, int y){
	int ret = 1;
	for(; y; y >>= 1, x = x * x % mod) if(y & 1) ret = ret * x % mod;
	return ret;
}
int rev[N], G_inv, len_inv;
void ntt(int *a, int len, int o){
	for(int i = 1; i <= len; i ++) if(i < rev[i]) swap(a[i], a[rev[i]]);
	for(int i = 2; i <= len; i <<= 1){
		int wn = qpow((o == 1)? G:G_inv, (mod - 1) / i);
		for(int j = 0, p = i / 2; j + i - 1 <= len; j += i){
			int w0 = 1;
			for(int k = j; k < j + p; k ++, w0 = w0 * wn % mod){
				int X = a[k], Y = w0 * a[k + p] % mod;
				a[k] = (X + Y) % mod;
				a[k + p] = (X - Y + mod) % mod;
			}
		}
	}
}
int c[N];
void work(int *a, int *b, int sz){
	if(sz == 1) {b[0] = qpow(a[0], mod - 2); return;}
	work(a, b, (sz + 1) / 2);
	int len = 1;
	for(; len < sz + sz; len <<= 1);
	len_inv = qpow(len, mod - 2), G_inv = qpow(G, mod - 2);
	for(int i = 0; i <= len; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i&1) * len>>1), c[i] = a[i];
	for(int i = sz; i <= len; i ++) c[i] = 0;
	ntt(c, len, 1), ntt(b, len, 1);
	for(int i = 0; i <= len; i ++) b[i] = (2ll * b[i] % mod - c[i] * b[i] % mod * b[i] % mod + mod) % mod;
	ntt(b, len, -1);
	for(int i = 0; i <= len; i ++) b[i] = b[i] * len_inv % mod;
	for(int i = sz; i <= len; i ++) b[i] = 0;
}
int n, m, a[N], b[N];
signed main(){
	scanf("%lld", &n);
	for(int i = 1; i < n; i ++) scanf("%lld", &a[i]), a[i] = (mod - a[i]) % mod;
	a[0] = 1;
	work(a, b, n);
	for(int i = 0; i < n; i ++) printf("%lld ", b[i]);
	return 0;
}

任意模数NTT

#include<bits/stdc++.h>
#define N 4000005
#define ll long long
#define double long double
using namespace std;
const double pi = acos(-1);
const double eps = 0.49;
const int C = 32768;
struct cp {
	double a, b;
}X[N], Y[N], Xd[N];
cp operator +(cp x, cp y) {return cp{x.a + y.a, x.b + y.b};}
cp operator -(cp x, cp y) {return cp{x.a - y.a, x.b - y.b};}
cp operator *(cp x, cp y) {return cp{x.a * y.a - x.b * y.b, x.b * y.a + x.a * y.b};}
int rev[N], n, m, P;
void fft(cp *a, int len, int o) {
	for(int i = 1; i <= len; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i&1) * len >> 1);
	for(int i = 1; i <= len; i ++) if(i < rev[i]) swap(a[i], a[rev[i]]);

	for(int i = 2; i <= len; i <<= 1) {
		cp wn = cp{cos(2 * pi / i), o * sin(2 * pi / i)};
		for(int j = 0, p = i / 2; j + i - 1 <= len; j += i) {
			cp w0 = cp{1, 0};
			for(int k = j; k < j + p; k ++, w0 = w0 * wn) {
				cp x = a[k], y =  w0 * a[k + p];
				a[k] = x + y;
				a[k + p] = x - y;
			}
		}
	}
	if(o == -1) for(int i = 0; i <= len; i ++) a[i].a /= len, a[i].b /= len;
}
int main() {
	scanf("%d%d", &n, &m);
	P = 1000000007;
	for(int i = 0; i <= n; i ++) {
		int x;
		scanf("%d", &x);
		X[i].a = x / C;
		X[i].b = x % C;
		Xd[i].a = x / C;
		Xd[i].b = -(x % C);
	}
	for(int i = 0; i <= m; i ++) {
		int x;
		scanf("%d", &x);
		Y[i].a = x / C;
		Y[i].b = x % C;
	}
	int len = 1;
	for(; len <= n + m;) len <<= 1;
	fft(X, len, 1), fft(Xd, len, 1), fft(Y, len, 1);
	for(int i = 0; i <= len; i ++) X[i] = X[i] * Y[i], Xd[i] = Xd[i] * Y[i];
	fft(X, len, -1), fft(Xd, len, -1);
	for(int i = 0; i <= n + m; i ++) {
		ll ac = (X[i].a + Xd[i].a) / 2 + eps;
		ll bd = Xd[i].a - ac + eps;
		ll bcad = X[i].b + eps;
		printf("%lld ", (ac * C % P * C % P + bcad * C % P + bd) % P);
	}
	return 0;
}

任意模数多项式求逆

code:

#include<bits/stdc++.h>
#define N 4000005
#define ll long long
#define double long double
using namespace std;
const double pi = acos(-1);
const double eps = 0.49;
const int C = 32768;
struct cp {
	double a, b;
}X[N], Y[N], Xd[N];
cp operator +(cp x, cp y) {return cp{x.a + y.a, x.b + y.b};}
cp operator -(cp x, cp y) {return cp{x.a - y.a, x.b - y.b};}
cp operator *(cp x, cp y) {return cp{x.a * y.a - x.b * y.b, x.b * y.a + x.a * y.b};}
int rev[N], P;
void fft(cp *a, int len, int o) {
	for(int i = 1; i <= len; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i&1) * len >> 1);
	for(int i = 1; i <= len; i ++) if(i < rev[i]) swap(a[i], a[rev[i]]);

	for(int i = 2; i <= len; i <<= 1) {
		cp wn = cp{cos(2 * pi / i), o * sin(2 * pi / i)};
		for(int j = 0, p = i / 2; j + i - 1 <= len; j += i) {
			cp w0 = cp{1, 0};
			for(int k = j; k < j + p; k ++, w0 = w0 * wn) {
				cp x = a[k], y =  w0 * a[k + p];
				a[k] = x + y;
				a[k + p] = x - y;
			}
		}
	}
	if(o == -1) for(int i = 0; i <= len; i ++) a[i].a /= len, a[i].b /= len;
}
void mul(ll *a, ll *b, int n, int m) {
	for(int i = 0; i <= n; i ++) {
		X[i].a = a[i] / C;
		X[i].b = a[i] % C;
		Xd[i].a = a[i] / C;
		Xd[i].b = -(a[i] % C);
	}
	for(int i = 0; i <= m; i ++) {
		Y[i].a = b[i] / C;
		Y[i].b = b[i] % C;
	}
	int len = 1;
	for(; len <= n + m;) len <<= 1;
	fft(X, len, 1), fft(Xd, len, 1), fft(Y, len, 1);
	for(int i = 0; i <= len; i ++) X[i] = X[i] * Y[i], Xd[i] = Xd[i] * Y[i];
	fft(X, len, -1), fft(Xd, len, -1);
	for(int i = 0; i <= n + m; i ++) {
		ll ac = (X[i].a + Xd[i].a) / 2 + eps;
		ll bd = Xd[i].a - ac + eps;
		ll bcad = X[i].b + eps;
		a[i] = (ac % P * C % P * C % P + bcad % P * C % P + bd % P) % P;
	}
	for(int i = 0; i <= len; i ++) X[i].a = X[i].b = Y[i].a = Y[i].b = Xd[i].a = Xd[i].b = 0;
}
int qpow(ll x, int y) {
	ll ret = 1;
	for(; y; y >>= 1, x = x * x % P) if(y & 1) ret = ret * x % P;
	return ret;
}
ll c[N], d[N], e[N], n;
void inv(ll *a, ll *b, int sz){
	if(sz == 0) {b[0] = qpow(a[0], P - 2); return;}
	inv(a, b, sz / 2);
	int len = 1;
	for(; len <= sz + sz; len <<= 1);
	for(int i = 0; i <= sz; i ++) c[i] = a[i];
	for(int i = sz + 1; i <= len; i ++) c[i] = 0;
	
	//for(int i = 0; i <= len; i ++) b[i] = (b[i] * 2 % mod - b[i] * b[i] % mod * c[i] % mod + mod) % mod;//Ö±½ÓËã
	
	for(int i = 0; i <= sz; i ++) e[i] = b[i] * 2 % P;
	for(int i = sz + 1; i <= len; i ++) e[i] = 0;
	
	for(int i = 0; i <= sz; i ++) d[i] = b[i]; 
	for(int i = sz + 1; i <= len; i ++) d[i] = 0;
	
	mul(b, d, sz, sz); mul(b, c, sz, sz);
	for(int i = 0; i <= sz; i ++) b[i] = (e[i] - b[i] + P) % P;
	
	for(int i = sz + 1; i <= len; i ++) b[i] = 0;
	
}
ll a[N], b[N];
int main() {
	scanf("%d", &n);
	n --;
	P = 1000000007; //模数
	for(int i = 0; i <= n; i ++) scanf("%lld", &a[i]);
	inv(a, b, n);
	for(int i = 0; i <= n; i ++) printf("%lld ", b[i]);
	return 0;
}

多项式对数函数(多项式 ln)

#include<bits/stdc++.h>
#define int long long
#define mod 998244353	
#define G 3
#define N 8000005
using namespace std;
int qpow(int x, int y){
	int ret = 1;
	for(; y; y >>= 1, x = x * x % mod) if(y & 1) ret = ret * x % mod;
	return ret;
}
int rev[N], G_inv, len_inv;
void ntt(int *a, int len, int o){
	len_inv = qpow(len, mod - 2);
	for(int i = 0; i <= len; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i&1) * len >> 1);
	for(int i = 0; i <= len; i ++) if(i < rev[i]) swap(a[i], a[rev[i]]);
	for(int i = 2; i <= len; i <<= 1){
		int wn = qpow((o == 1)? G:G_inv, (mod - 1) / i);
		for(int j = 0, p = i / 2; j + i - 1 <= len; j += i){
			int w0 = 1;
			for(int k = j; k < j + p; k ++, w0 = w0 * wn % mod){
				int X = a[k], Y = w0 * a[k + p] % mod;
				a[k] = (X + Y) % mod;
				a[k + p] = (X - Y + mod) % mod;
			}
		}
	}
	if(o == -1) 
		for(int i = 0; i <= len; i ++) a[i] = a[i] * len_inv % mod;
}
int c[N];
void inv(int *a, int *b, int sz){
	if(sz == 0) {b[0] = qpow(a[0], mod - 2); return;}
	inv(a, b, sz / 2);
	int len = 1;
	for(; len <= sz + sz; len <<= 1);
	for(int i = 0; i <= sz; i ++) c[i] = a[i];
	for(int i = sz + 1; i <= len; i ++) c[i] = 0;
	ntt(c, len, 1), ntt(b, len, 1);
	for(int i = 0; i <= len; i ++) b[i] = (b[i] * 2 % mod - b[i] * b[i] % mod * c[i] % mod + mod) % mod;
	ntt(b, len, -1);
	for(int i = sz + 1; i <= len; i ++) b[i] = 0;
}
void qiudao(int *a, int sz) {
	for(int i = 0; i < sz; i ++) a[i] = a[i + 1] * (i + 1) % mod;
	a[sz] = 0;
}
void jifen(int *a, int sz) {
	for(int i = sz; i >= 1; i --) a[i] = a[i - 1] * qpow(i, mod - 2) % mod;
	a[0] = 0;
}
void mul(int * a, int *b, int sz) {
	int len = 1;
	for(;len <= sz + sz;) len <<= 1;
	ntt(a, len, 1), ntt(b, len, 1);
	for(int i = 0; i <= len; i ++) a[i] = a[i] * b[i] % mod;
	ntt(a, len, -1);
}
int Ad[N], An[N];
void ln(int *A, int n) {
	for(int i = 0; i <= n; i ++) Ad[i] = A[i];
	qiudao(Ad, n);
	inv(A, An, n);
	mul(Ad, An, n);
	jifen(Ad, n);
	for(int i = 0; i <= n; i ++) A[i] = Ad[i];
}
int a[N], b[N], n, m;
signed main(){
	G_inv = qpow(G, mod - 2);
	scanf("%lld", &n); n --;
	for(int i = 0; i <= n; i ++) scanf("%lld", &a[i]);
	ln(a, n); 
	for(int i = 0; i <= n; i ++) printf("%lld ", a[i]);
	return 0;
}

多项式指数函数(多项式 exp)


#include<bits/stdc++.h>
#define int long long
#define mod 998244353	
#define G 3
#define N 8000005
using namespace std;
int qpow(int x, int y){
	int ret = 1;
	for(; y; y >>= 1, x = x * x % mod) if(y & 1) ret = ret * x % mod;
	return ret;
}
int rev[N], G_inv, len_inv;
void ntt(int *a, int len, int o){
	len_inv = qpow(len, mod - 2);
	for(int i = 0; i <= len; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i&1) * len >> 1);
	for(int i = 0; i <= len; i ++) if(i < rev[i]) swap(a[i], a[rev[i]]);
	for(int i = 2; i <= len; i <<= 1){
		int wn = qpow((o == 1)? G:G_inv, (mod - 1) / i);
		for(int j = 0, p = i / 2; j + i - 1 <= len; j += i){
			int w0 = 1;
			for(int k = j; k < j + p; k ++, w0 = w0 * wn % mod){
				int X = a[k], Y = w0 * a[k + p] % mod;
				a[k] = (X + Y) % mod;
				a[k + p] = (X - Y + mod) % mod;
			}
		}
	}
	if(o == -1) 
		for(int i = 0; i <= len; i ++) a[i] = a[i] * len_inv % mod;
}
int c[N];
void inv(int *a, int *b, int sz){
	if(sz == 0) {b[0] = qpow(a[0], mod - 2); return;}
	inv(a, b, sz / 2);
	int len = 1;
	for(; len <= sz + sz; len <<= 1);
	for(int i = 0; i <= sz; i ++) c[i] = a[i];
	for(int i = sz + 1; i <= len; i ++) c[i] = 0;
	ntt(c, len, 1), ntt(b, len, 1);
	for(int i = 0; i <= len; i ++) b[i] = (b[i] * 2 % mod - b[i] * b[i] % mod * c[i] % mod + mod) % mod;
	ntt(b, len, -1);
	for(int i = sz + 1; i <= len; i ++) b[i] = 0;
}
void qiudao(int *a, int sz) {
	for(int i = 0; i < sz; i ++) a[i] = a[i + 1] * (i + 1) % mod;
	a[sz] = 0;
}
void jifen(int *a, int sz) {
	for(int i = sz; i >= 1; i --) a[i] = a[i - 1] * qpow(i, mod - 2) % mod;
	a[0] = 0;
}
int Ad[N], An[N];
void ln(int *A, int n) {
	for(int i = 0; i <= n; i ++) Ad[i] = A[i];
	qiudao(Ad, n);
	inv(A, An, n);
	int len = 1;
	for(; len <= n + n;) len <<= 1;
	ntt(Ad, len, 1), ntt(An, len, 1);
	for(int i = 0; i <= len; i ++) Ad[i] = Ad[i] * An[i] % mod;
	ntt(Ad, len, -1);
	jifen(Ad, n);
	for(int i = 0; i <= len; i ++) An[i] = 0;
	for(int i = 0; i <= n; i ++) A[i] = Ad[i];
}
int fln[N];
void exp(int *a, int *b, int n) {
	if(n == 0) {b[0] = 1; return;}
	exp(a, b, n / 2); 
	for(int i = 0; i <= n; i ++) fln[i] = b[i]; ln(fln, n);
	fln[0] = 1;
	for(int i = 1; i <= n; i ++) fln[i] = (a[i] - fln[i] + mod ) % mod;
	int len = 1;
	for(; len <= n + n;) len <<= 1;
	ntt(b, len, 1), ntt(fln, len, 1);
	for(int i = 0; i <= len; i ++) b[i] = b[i] * fln[i] % mod;
	ntt(b, len, -1);
	for(int i = 0; i <= len; i ++) fln[i] = 0;
}
int a[N], b[N], n, m;
signed main(){
	G_inv = qpow(G, mod - 2);
	scanf("%lld", &n); n --;
	for(int i = 0; i <= n; i ++) scanf("%lld", &a[i]);
	exp(a, b, n); 
	for(int i = 0; i <= n; i ++) printf("%lld ", b[i]);
	return 0;
}

多项式开根

#include<bits/stdc++.h>
#define int long long
#define mod 998244353	
#define G 3
#define N 8000005
using namespace std;
int qpow(int x, int y){
	int ret = 1;
	for(; y; y >>= 1, x = x * x % mod) if(y & 1) ret = ret * x % mod;
	return ret;
}
int rev[N], G_inv, len_inv;
void ntt(int *a, int len, int o){
	len_inv = qpow(len, mod - 2);
	for(int i = 0; i <= len; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i&1) * len >> 1);
	for(int i = 0; i <= len; i ++) if(i < rev[i]) swap(a[i], a[rev[i]]);
	for(int i = 2; i <= len; i <<= 1){
		int wn = qpow((o == 1)? G:G_inv, (mod - 1) / i);
		for(int j = 0, p = i / 2; j + i - 1 <= len; j += i){
			int w0 = 1;
			for(int k = j; k < j + p; k ++, w0 = w0 * wn % mod){
				int X = a[k], Y = w0 * a[k + p] % mod;
				a[k] = (X + Y) % mod;
				a[k + p] = (X - Y + mod) % mod;
			}
		}
	}
	if(o == -1) 
		for(int i = 0; i <= len; i ++) a[i] = a[i] * len_inv % mod;
}
int c[N];
void inv(int *a, int *b, int sz){
	if(sz == 0) {b[0] = qpow(a[0], mod - 2); return;}
	inv(a, b, sz / 2);
	int len = 1;
	for(; len <= sz + sz; len <<= 1);
	for(int i = 0; i <= sz; i ++) c[i] = a[i];
	for(int i = sz + 1; i <= len; i ++) c[i] = 0;
	ntt(c, len, 1), ntt(b, len, 1);
	for(int i = 0; i <= len; i ++) b[i] = (b[i] * 2 % mod - b[i] * b[i] % mod * c[i] % mod + mod) % mod;
	ntt(b, len, -1);
	for(int i = sz + 1; i <= len; i ++) b[i] = 0;
}
void qiudao(int *a, int sz) {
	for(int i = 0; i < sz; i ++) a[i] = a[i + 1] * (i + 1) % mod;
	a[sz] = 0;
}
void jifen(int *a, int sz) {
	for(int i = sz; i >= 1; i --) a[i] = a[i - 1] * qpow(i, mod - 2) % mod;
	a[0] = 0;
}
int Ad[N], An[N];
void ln(int *A, int n) {
	for(int i = 0; i <= n; i ++) Ad[i] = A[i];
	qiudao(Ad, n);
	inv(A, An, n);
	int len = 1;
	for(; len <= n + n;) len <<= 1;
	ntt(Ad, len, 1), ntt(An, len, 1);
	for(int i = 0; i <= len; i ++) Ad[i] = Ad[i] * An[i] % mod;
	ntt(Ad, len, -1);
	jifen(Ad, n);
	for(int i = 0; i <= n; i ++) A[i] = Ad[i];
	for(int i = 0; i <= len; i ++) An[i] = Ad[i] = 0;
}
int fln[N];
void exp(int *a, int *b, int n) {
	if(n == 0) {b[0] = 1; return;}
	exp(a, b, n / 2); 
	for(int i = 0; i <= n; i ++) fln[i] = b[i]; ln(fln, n);
	fln[0] = 1;
	for(int i = 1; i <= n; i ++) fln[i] = (a[i] - fln[i] + mod ) % mod;
	int len = 1;
	for(; len <= n + n;) len <<= 1;
	ntt(b, len, 1), ntt(fln, len, 1);
	for(int i = 0; i <= len; i ++) b[i] = b[i] * fln[i] % mod;
	ntt(b, len, -1);
	for(int i = 0; i <= len; i ++) fln[i] = 0;
}
int a[N], b[N], n, m;
signed main(){
	G_inv = qpow(G, mod - 2);
	scanf("%lld", &n); n --;
	for(int i = 0; i <= n; i ++) scanf("%lld", &a[i]);
	ln(a, n);
	for(int i = 0; i <= n; i ++) a[i] = a[i] * qpow(2, mod - 2) % mod;
	exp(a, b, n); 
	for(int i = 0; i <= n; i ++) printf("%lld ", b[i]);
	return 0;
}

多项式快速幂


#include<bits/stdc++.h>
#define int long long
#define mod 998244353	
#define G 3
#define N 8000005
using namespace std;
int qpow(int x, int y){
	int ret = 1;
	for(; y; y >>= 1, x = x * x % mod) if(y & 1) ret = ret * x % mod;
	return ret;
}
int rev[N], G_inv, len_inv;
void ntt(int *a, int len, int o){
	len_inv = qpow(len, mod - 2);
	for(int i = 0; i <= len; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i&1) * len >> 1);
	for(int i = 0; i <= len; i ++) if(i < rev[i]) swap(a[i], a[rev[i]]);
	for(int i = 2; i <= len; i <<= 1){
		int wn = qpow((o == 1)? G:G_inv, (mod - 1) / i);
		for(int j = 0, p = i / 2; j + i - 1 <= len; j += i){
			int w0 = 1;
			for(int k = j; k < j + p; k ++, w0 = w0 * wn % mod){
				int X = a[k], Y = w0 * a[k + p] % mod;
				a[k] = (X + Y) % mod;
				a[k + p] = (X - Y + mod) % mod;
			}
		}
	}
	if(o == -1) 
		for(int i = 0; i <= len; i ++) a[i] = a[i] * len_inv % mod;
}
int c[N];
void inv(int *a, int *b, int sz){
	if(sz == 0) {b[0] = qpow(a[0], mod - 2); return;}
	inv(a, b, sz / 2);
	int len = 1;
	for(; len <= sz + sz; len <<= 1);
	for(int i = 0; i <= sz; i ++) c[i] = a[i];
	for(int i = sz + 1; i <= len; i ++) c[i] = 0;
	ntt(c, len, 1), ntt(b, len, 1);
	for(int i = 0; i <= len; i ++) b[i] = (b[i] * 2 % mod - b[i] * b[i] % mod * c[i] % mod + mod) % mod;
	ntt(b, len, -1);
	for(int i = sz + 1; i <= len; i ++) b[i] = 0;
}
void qiudao(int *a, int sz) {
	for(int i = 0; i < sz; i ++) a[i] = a[i + 1] * (i + 1) % mod;
	a[sz] = 0;
}
void jifen(int *a, int sz) {
	for(int i = sz; i >= 1; i --) a[i] = a[i - 1] * qpow(i, mod - 2) % mod;
	a[0] = 0;
}
int Ad[N], An[N];
void ln(int *A, int n) {
	for(int i = 0; i <= n; i ++) Ad[i] = A[i];
	qiudao(Ad, n);
	inv(A, An, n);
	int len = 1;
	for(; len <= n + n;) len <<= 1;
	ntt(Ad, len, 1), ntt(An, len, 1);
	for(int i = 0; i <= len; i ++) Ad[i] = Ad[i] * An[i] % mod;
	ntt(Ad, len, -1);
	jifen(Ad, n);
	for(int i = 0; i <= n; i ++) A[i] = Ad[i];
	for(int i = 0; i <= len; i ++) An[i] = Ad[i] = 0;
}
int fln[N];
void exp(int *a, int *b, int n) {
	if(n == 0) {b[0] = 1; return;}
	exp(a, b, n / 2); 
	for(int i = 0; i <= n; i ++) fln[i] = b[i]; ln(fln, n);
	fln[0] = 1;
	for(int i = 1; i <= n; i ++) fln[i] = (a[i] - fln[i] + mod ) % mod;
	int len = 1;
	for(; len <= n + n;) len <<= 1;
	ntt(b, len, 1), ntt(fln, len, 1);
	for(int i = 0; i <= len; i ++) b[i] = b[i] * fln[i] % mod;
	ntt(b, len, -1);
	for(int i = 0; i <= len; i ++) fln[i] = 0;
}
int a[N], b[N], n, m;
char st[N];
signed main(){
	G_inv = qpow(G, mod - 2);
	scanf("%lld", &n); n --;
	scanf("%s", st + 1);
	int nn = strlen(st + 1);
	int M = 0;
	for(int i = 1; i <= nn; i ++) M = M * 10 + st[i] - '0', M %= mod;
	for(int i = 0; i <= n; i ++) scanf("%lld", &a[i]);
	ln(a, n);
	for(int i = 0; i <= n; i ++) a[i] = a[i] * M % mod;
	exp(a, b, n); 
	for(int i = 0; i <= n; i ++) printf("%lld ", b[i]);
	return 0;
}
发布了157 篇原创文章 · 获赞 90 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_38944163/article/details/101776530