多项式模板

#include <bits/stdc++.h>
#define For(i, x, y) for (int i = (x); i <= (y); i ++)
#define sz(v) (int)(v.size())
using namespace std;
int ksm(int x, int y, int p) {
    int v = 1; x %= p;
    while (y) v = 1ll * v * ((y & 1) ? x : 1) % p, x = 1ll * x * x % p, y >>= 1;
    return v % p;
}
namespace Poly {
	typedef vector< int > poly;
	const int mod = 998244353, G = 3, invG = ksm(3, mod - 2, mod);
	vector< int > id;
	poly get (poly a, int n) {
		a.resize(n, 0);
		return a;
	}
	poly NTT (poly a, int op) {
		int n = sz(a);
		For (i, 0, n - 1) if (i < id[i]) swap(a[i], a[id[i]]);
		for (int k = 1; k < n; k <<= 1) {
			int wn = ksm(op == 1 ? G : invG, (mod - 1) / (k << 1), mod);
			for (int i = 0; i < n; i += (k << 1)) {
				int w = 1;
				for (int j = 0; j < k; j ++, w = 1ll * w * wn % mod) {
					int x = a[i + j], y = 1ll * w * a[i + j + k] % mod;
					a[i + j] = (x + y) % mod; a[i + j + k] = (x - y + mod) % mod;
				}
			}
		}
		if (op == -1) {
			int val = ksm(n, mod - 2, mod);
			For (i, 0, n - 1) a[i] = 1ll * a[i] * val % mod;
		}
		return a;
	}
	poly operator * (poly a, poly b) {
		int n = sz(a), m = sz(b), k = 0;
		while ((1 << k) <= n + m - 2) k ++;
		id.resize(1 << k);
		For (i, 1, (1 << k) - 1) id[i] = ((id[i >> 1] >> 1) | ((i & 1) << (k - 1)));
		a.resize(1 << k, 0); b.resize(1 << k, 0); a = NTT(a, 1); b = NTT(b, 1);
		For (i, 0, (1 << k) - 1) a[i] = 1ll * a[i] * b[i] % mod;
		a = NTT(a, -1); a.resize(n + m - 1, 0);
		return a;
	}
	poly operator + (poly a, poly b) {
		int n = sz(a), m = sz(b); n = max(n, m); a.resize(n, 0); b.resize(n, 0);
		For (i, 0, n - 1) a[i] += b[i], (a[i] >= mod) && (a[i] -= mod);
		return a;
	}
	poly operator - (poly a, poly b) {
		int n = sz(a), m = sz(b); n = max(n, m); a.resize(n, 0); b.resize(n, 0);
		For (i, 0, n - 1) a[i] += mod - b[i], (a[i] >= mod) && (a[i] -= mod);
		return a;
	}
	poly mul (poly a, int v) {
		for (int &x : a) x = 1ll * x * v % mod;
		return a;
	}
	poly inv (poly a) {
		int n = sz(a);
		if (n == 1) return poly{ksm(a[0], mod - 2, mod)};
		poly b = inv(get(a, (n + 1) >> 1));
		return get(mul(b, 2) - a * b * b, n);
	}
	poly deriv (poly a) {
		int n = sz(a); poly b(n - 1);
		For (i, 0, n - 2) b[i] = 1ll * (i + 1) * a[i + 1] % mod;
		return b;
	}
	poly integ (poly a) {
		int n = sz(a); poly b(n + 1, 0);
		For (i, 1, n) b[i] = 1ll * a[i - 1] * ksm(i, mod - 2, mod) % mod;
		return b;
	}
	poly ln (poly a) {
		return integ(get(deriv(a) * inv(a), sz(a) - 1));
	} 
	poly exp (poly a, int n = 0) {
		if (sz(a) == 1) return poly{1};
		if (!n) n = sz(a);
		const poly b = exp(get(a, (sz(a) + 1) >> 1), sz(a));
		return get(b * (a - ln(b)) + b, n);
	}
	poly operator ^ (poly a, int k) {
		return exp(mul(ln(a), k));
	}
}
using namespace Poly;
int main () {
    ios :: sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
	return 0;
}

作者:lycc2009

出处:https://www.cnblogs.com/lycc2009/p/18508610

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   lycc2009  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示