QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#563155#4903. 细菌Elegia100 ✓631ms14376kbC++2324.3kb2024-09-14 03:10:362024-09-14 03:10:37

Judging History

你现在查看的是最新测评结果

  • [2024-09-14 03:10:37]
  • 评测
  • 测评结果:100
  • 用时:631ms
  • 内存:14376kb
  • [2024-09-14 03:10:36]
  • 提交

answer

#include <cstdio>
#include <cstring>

#include <algorithm>
#include <chrono>
#include <random>
#include <functional>
#include <vector>

#define LOG(FMT...) fprintf(stderr, FMT)

using namespace std;

typedef long long ll;

const int P = 998244353, R = 3;
const int BRUTE_N2_LIMIT = 50;

int mpow(int x, int k, int p = P) {
	int ret = 1;
	while (k) {
	if (k & 1)
		ret = ret * (ll) x % p;
	x = x * (ll) x % p;
	k >>= 1;
	}
	return ret;
}

int norm(int x) { return x >= P ? x - P : x; }

void add(int& x, int y) {
	if ((x += y) >= P)
	x -= P;
}

void sub(int& x, int y) {
	if ((x -= y) < 0)
	x += P;
}

struct NumberTheory {

	typedef pair<int, int> _P2_Field;

	mt19937 rng;

	NumberTheory() : rng(chrono::steady_clock::now().time_since_epoch().count()) {}

	void _exGcd(int a, int b, int &x, int &y) {
	if (!b) {
		x = 1;
		y = 0;
		return;
	}
	_exGcd(b, a % b, y, x);
	y -= a / b * x;
	}

	int inv(int a, int p = P) {
	int x, y;
	_exGcd(a, p, x, y);
	if (x < 0)
		x += p;
	return x;
	}

	template<class Integer>
	bool quadRes(Integer a, Integer b) {
	if (a <= 1)
		return true;
	while (a % 4 == 0)
		a /= 4;
	if (a % 2 == 0)
		return (b % 8 == 1 || b % 8 == 7) == quadRes(a / 2, b);
	return ((a - 1) % 4 == 0 || (b - 1) % 4 == 0) == quadRes(b % a, a);
	}

	// assume p in prime, x in quadratic residue
	int sqrt(int x, int p = P) {
	if (p == 2 || x <= 1)
		return x;
	int w, v, k = (p + 1) / 2;
	do {
		w = rng() % p;
	} while (quadRes(v = int((w * (ll) w - x + p) % p), p));
	_P2_Field res(1, 0), a(w, 1);
	while (k) {
		if (k & 1)
		res = _P2_Field((res.first * (ll) a.first + res.second * (ll) a.second % p * v) % p,
						(res.first * (ll) a.second + res.second * (ll) a.first) % p);
		if (k >>= 1)
		a = _P2_Field((a.first * (ll) a.first + a.second * (ll) a.second % p * v) % p,
						(a.first * (ll) a.second << 1) % p);
	}
	return min(res.first, p - res.first);
	}

} nt;

template<class T, class Comp>
struct AdditionChain {
	int k;
	vector<T> prepare;
	T t, unit;
	Comp comp;

	AdditionChain(const T &t, const Comp &comp, int k, const T &unit = 1) : comp(comp), t(t), unit(unit), k(k),
																			prepare(1U << k) {
	prepare[0] = unit;
	for (int i = 1; i < 1 << k; ++i)
		prepare[i] = comp(prepare[i - 1], t);
	}

	static AdditionChain fourRussians(const T &t, const Comp &comp, int lgn, const T &unit = 1) {
	lgn = max(lgn, 1);
	int k = 1, lglgn = 1;
	while (2 << lglgn <= lgn)
		++lglgn;
	int w = lglgn / lgn;
	while (1 << k < w)
		++k;
	return AdditionChain(t, comp, k, unit);
	}

	T pow(int n) const {
	if (n < 1 << k)
		return prepare[n];
	int r = n & ((1 << k) - 1);
	T step = pow(n >> k);
	for (int rep = 0; rep < k; ++rep)
		step = comp(step, step);
	return comp(step, prepare[r]);
	}
};

struct Simple {
	int n;
	vector<int> fac, ifac, inv;

	void build(int n) {
	this->n = n;
	fac.resize(n + 1);
	ifac.resize(n + 1);
	inv.resize(n + 1);
	fac[0] = 1;
	for (int x = 1; x <= n; ++x)
		fac[x] = fac[x - 1] * (ll) x % P;
	inv[1] = 1;
	for (int x = 2; x <= n; ++x)
		inv[x] = -(P / x) * (ll) inv[P % x] % P + P;
	ifac[0] = 1;
	for (int x = 1; x <= n; ++x)
		ifac[x] = ifac[x - 1] * (ll) inv[x] % P;
	}

	Simple() {
	build(1);
	}

	void check(int k) {
	int nn = n;
	if (k > nn) {
		while (k > nn)
		nn <<= 1;
		build(nn);
	}
	}

	int gfac(int k) {
	check(k);
	return fac[k];
	}

	int gifac(int k) {
	check(k);
	return ifac[k];
	}

	int ginv(int k) {
	check(k);
	return inv[k];
	}

	int binom(int n, int m) {
	if (m < 0 || m > n)
		return 0;
	return gfac(n) * (ll) gifac(m) % P * gifac(n - m) % P;
	}
} simp;

const int L2 = 11;

struct NTT {
	int L;
	int brev[1 << L2];
	vector<int> root;

	NTT() : L(-1) {
	for (int i = 1; i < (1 << L2); ++i)
		brev[i] = brev[i >> 1] >> 1 | ((i & 1) << (L2 - 1));
	}

	void prepRoot(int l) {
	L = l;
	root.resize(2 << L);
	for (int i = 0; i <= L; ++i) {
		int* w = root.data() + (1 << i);
		w[0] = 1;
		int omega = mpow(R, (P - 1) >> i);
		for (int j = 1; j < 1 << i; ++j)
		w[j] = w[j - 1] * (ll)omega % P;
	}
	}

	void fft(int *a, int lgn, int d = 1) {
	if (L < lgn) prepRoot(lgn);
	int n = 1 << lgn;
	for (int i = 0; i < n; ++i) {
		int rev = (brev[i >> L2] | (brev[i & ((1 << L2) - 1)] << L2)) >> ((L2 << 1) - lgn);
		if (i < rev)
		swap(a[i], a[rev]);
	}
	for (int i = 1; i < n; i <<= 1) {
		int* w = root.data() + (i << 1);
		for (int j = 0; j < n; j += i << 1) {
		for (int k = 0; k < i; ++k) {
			int aa = w[k] * (ll)a[i + j + k] % P;
			a[i + j + k] = norm(a[j + k] + P - aa);
			add(a[j + k], aa);
		}
		}
	}
	if (d == -1) {
		reverse(a + 1, a + n);
		int nv = mpow(n, P - 2);
		for (int i = 0; i < n; ++i) a[i] = a[i] * (ll) nv % P;
	}
	}
} ntt;

struct Poly {
	vector<int> a;

	Poly(int v = 0) : a(1) {
	if ((v %= P) < 0)
		v += P;
	a[0] = v;
	}

	Poly(const vector<int> &a) : a(a) {}

	Poly(initializer_list<int> init) : a(init) {}

	// Helps
	int operator[](int k) const { return k < a.size() ? a[k] : 0; }

	int &operator[](int k) {
	if (k >= a.size())
		a.resize(k + 1);
	return a[k];
	}

	int deg() const { return a.size() - 1; }

	void redeg(int d) { a.resize(d + 1); }

	Poly monic() const;

	Poly sunic() const;

	Poly slice(int d) const {
	if (d < a.size())
		return vector<int>(a.begin(), a.begin() + d + 1);
	vector<int> res(a);
	res.resize(d + 1);
	return res;
	}

	int *base() { return a.data(); }

	const int *base() const { return a.data(); }

	Poly println(FILE *fp) const {
	fprintf(fp, "%d", a[0]);
	for (int i = 1; i < a.size(); ++i)
		fprintf(fp, " %d", a[i]);
	fputc('\n', fp);
	return *this;
	}

	// Calculations
	Poly operator+(const Poly &rhs) const {
	vector<int> res(max(a.size(), rhs.a.size()));
	for (int i = 0; i < res.size(); ++i)
		if ((res[i] = operator[](i) + rhs[i]) >= P)
		res[i] -= P;
	return res;
	}

	Poly operator-() const {
	Poly ret(a);
	for (int i = 0; i < a.size(); ++i)
		if (ret[i])
		ret[i] = P - ret[i];
	return ret;
	}

	Poly operator-(const Poly &rhs) const { return operator+(-rhs); }

	Poly operator*(const Poly &rhs) const;

	Poly operator/(const Poly &rhs) const;

	Poly operator%(const Poly &rhs) const;

	Poly der() const; // default: remove trailing
	Poly integ() const;

	Poly inv() const;

	Poly sqrt() const;

	Poly ln() const;

	Poly exp() const;

	pair<Poly, Poly> sqrti() const;

	pair<Poly, Poly> expi() const;

	Poly quo(const Poly &rhs) const;

	pair<Poly, Poly> iquo(const Poly &rhs) const;

	pair<Poly, Poly> div(const Poly &rhs) const;

	Poly taylor(int k) const;

	Poly pow(int k) const;

	Poly exp(int k) const;
};

Poly zeroes(int deg) { return vector<int>(deg + 1); }

struct Newton {
	void inv(const Poly &f, const Poly &nttf, Poly &g, const Poly &nttg, int t) {
	int n = 1 << t;
	Poly prod = nttf;
	for (int i = 0; i < (n << 1); ++i)
		prod[i] = prod[i] * (ll) nttg[i] % P;
	ntt.fft(prod.base(), t + 1, -1);
	for (int i = 0; i < n; ++i)
		prod[i] = 0;
	ntt.fft(prod.base(), t + 1, 1);
	for (int i = 0; i < (n << 1); ++i)
		prod[i] = prod[i] * (ll) nttg[i] % P;
	ntt.fft(prod.base(), t + 1, -1);
	for (int i = 0; i < n; ++i)
		prod[i] = 0;
	g = g - prod;
	}

	void inv(const Poly &f, const Poly &nttf, Poly &g, int t) {
	Poly nttg = g;
	nttg.redeg((2 << t) - 1);
	ntt.fft(nttg.base(), t + 1, 1);
	inv(f, nttf, g, nttg, t);
	}

	void inv(const Poly &f, Poly &g, int t) {
	Poly nttg = g;
	nttg.redeg((2 << t) - 1);
	ntt.fft(nttg.base(), t + 1, 1);
	Poly nttf = f;
	nttf.redeg((2 << t) - 1);
	ntt.fft(nttf.base(), t + 1, 1);
	inv(f, nttf, g, nttg, t);
	}

	void sqrt(const Poly &f, Poly &g, Poly &nttg, Poly &h, int t) {
	for (int i = 0; i < (1 << t); ++i)
		nttg[i] = mpow(nttg[i], 2);
	ntt.fft(nttg.base(), t, -1);
	nttg = nttg - f;
	for (int i = 0; i < (1 << t); ++i)
		if ((nttg[i + (1 << t)] += nttg[i]) >= P)
		nttg[i + (1 << t)] -= P;
	memset(nttg.base(), 0, sizeof(int) << t);
	ntt.fft(nttg.base(), t + 1, 1);
	Poly tmp = h;
	tmp.redeg((2 << t) - 1);
	ntt.fft(tmp.base(), t + 1, 1);
	for (int i = 0; i < (2 << t); ++i)
		tmp[i] = tmp[i] * (ll) nttg[i] % P;
	ntt.fft(tmp.base(), t + 1, -1);
	memset(tmp.base(), 0, sizeof(int) << t);
	g = g - tmp * nt.inv(2);
	}

	void exp(const Poly &f, Poly &g, Poly &nttg, Poly &h, int t) {
	Poly ntth(h);
	ntt.fft(ntth.base(), t, 1);
	Poly dg = g.der().slice((1 << t) - 1);
	ntt.fft(dg.base(), t, 1);
	Poly tmp = zeroes((1 << t) - 1);
	for (int i = 0; i < (1 << t); ++i) {
		tmp[i] = nttg[i << 1] * (ll) ntth[i] % P;
		dg[i] = dg[i] * (ll) ntth[i] % P;
	}
	ntt.fft(tmp.base(), t, -1);
	ntt.fft(dg.base(), t, -1);
	if (--tmp[0] < 0)
		tmp[0] = P - 1;
	dg.redeg((2 << t) - 1);
	Poly df0 = f.der().slice((1 << t) - 1);
	df0[(1 << t) - 1] = 0;
	for (int i = 0; i < (1 << t); ++i) {
		if ((dg[i | 1 << t] = dg[i] - df0[i]) < 0)
		dg[i | 1 << t] += P;
	}
	memcpy(dg.base(), df0.base(), sizeof(int) * ((1 << t) - 1));
	tmp.redeg((2 << t) - 1);
	ntt.fft(tmp.base(), t + 1, 1);
	df0.redeg((2 << t) - 1);
	ntt.fft(df0.base(), t + 1, 1);
	for (int i = 0; i < (2 << t); ++i)
		df0[i] = df0[i] * (ll) tmp[i] % P;
	ntt.fft(df0.base(), t + 1, -1);
	memcpy(df0.base() + (1 << t), df0.base(), sizeof(int) << t);
	memset(df0.base(), 0, sizeof(int) << t);
	dg = (dg - df0).integ().slice((2 << t) - 1) - f;
	ntt.fft(dg.base(), t + 1, 1);
	for (int i = 0; i < (2 << t); ++i)
		tmp[i] = dg[i] * (ll) nttg[i] % P;
	ntt.fft(tmp.base(), t + 1, -1);
	g.redeg((2 << t) - 1);
	for (int i = 1 << t; i < (2 << t); ++i)
		if (tmp[i])
		g[i] = P - tmp[i];
	}
} nit;

struct SemiRelaxedConvolution {

	template<class Function>
	void run(const vector<int> &a, vector<int> &b, const Function &relax) {
	int n = a.size() - 1;
	function<void(int, int)> divideConquer = [&](int l, int r) {
		if (r - l <= BRUTE_N2_LIMIT) {
		for (int i = l; i <= r; ++i) {
			for (int j = l; j < i; ++j)
			b[i] = (b[i] + b[j] * (ll) a[i - j]) % P;
			relax(i);
		}
		return;
		}
		int lg = 31 - __builtin_clz(r - l) + 1;
		int d = (r - l) / lg + 1;
		int lgd = 0;
		while ((1 << lgd) < d) ++lgd;
		++lgd;

		vector<int> top((lg << (lgd + 1)));
		for (int i = 0; i < lg; ++i) {
		copy(a.begin() + i * d, a.begin() + min((i + 2) * d, n + 1), top.begin() + (i << lgd));
		ntt.fft(top.data() + (i << lgd), lgd, 1);
		}
		for (int i = 0; i < lg; ++i) {
		if (i)
			ntt.fft(top.data() + ((lg + i) << lgd), lgd, -1);
		for (int j = 0; j < min(d, r - l - i * d + 1); ++j)
			b[l + i * d + j] = norm(b[l + i * d + j] + top[((lg + i) << lgd) + d + j]);
		divideConquer(l + i * d, min(l + (i + 1) * d - 1, r));
		if (i + 1 < lg) {
			copy(b.begin() + l + i * d, b.begin() + min(l + (i + 1) * d, n + 1), top.begin() + ((lg + i) << lgd));
			fill(top.data() + ((lg + i) << lgd) + d, top.data() + ((lg + i + 1) << lgd), 0);
			ntt.fft(top.data() + ((lg + i) << lgd), lgd, 1);
		}
		for (int j = i + 1; j < lg; ++j) {
			for (int k = 0; k < (1 << lgd); ++k)
			top[((lg + j) << lgd) + k] =
					(top[((lg + j) << lgd) + k] + top[((j - i - 1) << lgd) + k] * (ll) top[((lg + i) << lgd) + k]) % P;
		}
		}
	};
	divideConquer(0, n);
	}
} src;

struct Transposition {

	vector<int> _mul(int l, vector<int> res, const Poly &b) {
	vector<int> tmp(1 << l);
	memcpy(tmp.data(), b.a.data(), sizeof(int) * (b.deg() + 1));
	reverse(tmp.begin() + 1, tmp.end());
	ntt.fft(tmp.data(), l, 1);
	for (int i = 0; i < (1 << l); ++i)
		res[i] = res[i] * (ll) tmp[i] % P;
	ntt.fft(res.data(), l, -1);
	return res;
	}

	Poly bfMul(const Poly &a, const Poly &b) {
	int n = a.deg(), m = b.deg();
	Poly ret = zeroes(n - m);
	for (int i = 0; i <= n - m; ++i)
		for (int j = 0; j <= m; ++j)
		ret[i] = (ret[i] + a[i + j] * (ll) b[j]) % P;
	return ret;
	}

	Poly mul(const Poly &a, const Poly &b) {
	if (a.deg() < b.deg()) return 0;
	if (a.deg() <= BRUTE_N2_LIMIT) return bfMul(a, b);
	int l = 0;
	while ((1 << l) <= a.deg()) ++l;
	vector<int> res(1 << l);
	memcpy(res.data(), a.a.data(), sizeof(int) * (a.deg() + 1));
	ntt.fft(res.data(), l, 1);
	res = _mul(l, res, b);
	res.resize(a.deg() - b.deg() + 1);
	return res;
	}

	pair<Poly, Poly> mul2(const Poly &a, const Poly &b1, const Poly &b2) {
	if (a.deg() <= BRUTE_N2_LIMIT) return make_pair(bfMul(a, b1), bfMul(a, b2));
	int l = 0;
	while ((1 << l) <= a.deg()) ++l;
	vector<int> fa(1 << l);
	memcpy(fa.data(), a.a.data(), sizeof(int) * (a.deg() + 1));
	ntt.fft(fa.data(), l, 1);
	vector<int> res1 = _mul(l, fa, b1), res2 = _mul(l, fa, b2);
	res1.resize(a.deg() - b1.deg() + 1);
	res2.resize(a.deg() - b2.deg() + 1);
	return make_pair(res1, res2);
	}

	vector<int> ls, rs, pos;
	vector<Poly> p, q;

	void _build(int n) {
	ls.assign(n * 2 - 1, 0);
	rs.assign(n * 2 - 1, 0);
	p.assign(n * 2 - 1, 0);
	q.assign(n * 2 - 1, 0);
	pos.resize(n);
	int cnt = 0;
	function<int(int, int)> dfs = [&](int l, int r) {
		if (l == r) {
		pos[l] = cnt;
		return cnt++;
		}
		int ret = cnt++;
		int mid = (l + r) >> 1;
		ls[ret] = dfs(l, mid);
		rs[ret] = dfs(mid + 1, r);
		return ret;
	};
	dfs(0, n - 1);
	}

	vector<int> _eval(vector<int> f, const vector<int> &x) {
	int n = f.size();
	_build(n);
	for (int i = 0; i < n; ++i)
		q[pos[i]] = {1, norm(P - x[i])};
	for (int i = n * 2 - 2; i >= 0; --i)
		if (ls[i])
		q[i] = q[ls[i]] * q[rs[i]];
	f.resize(n * 2);
	p[0] = mul(f, q[0].inv());
	for (int i = 0; i < n * 2 - 1; ++i)
		if (ls[i])
		tie(p[ls[i]], p[rs[i]]) = mul2(p[i], q[rs[i]], q[ls[i]]);
	vector<int> ret(n);
	for (int i = 0; i < n; ++i)
		ret[i] = p[pos[i]][0];
	return ret;
	}

	vector<int> eval(const Poly &f, const vector<int> &x) {
	int n = f.deg() + 1, m = x.size();
	vector<int> tmpf = f.a, tmpx = x;
	tmpf.resize(max(n, m));
	tmpx.resize(max(n, m));
	vector<int> ret = _eval(tmpf, tmpx);
	ret.resize(m);
	return ret;
	}

	Poly inter(const vector<int> &x, const vector<int> &y) {
	int n = x.size();
	_build(n);
	for (int i = 0; i < n; ++i)
		q[pos[i]] = {1, norm(P - x[i])};
	for (int i = n * 2 - 2; i >= 0; --i)
		if (ls[i])
		q[i] = q[ls[i]] * q[rs[i]];
	Poly tmp = q[0];
	reverse(tmp.a.begin(), tmp.a.end());
	vector<int> f = tmp.der().a;
	f.resize(n * 2);
	p[0] = mul(f, q[0].inv());
	for (int i = 0; i < n * 2 - 1; ++i)
		if (ls[i])
		tie(p[ls[i]], p[rs[i]]) = mul2(p[i], q[rs[i]], q[ls[i]]);
	for (int i = 0; i < n; ++i)
		p[pos[i]] = nt.inv(p[pos[i]][0]) * (ll) y[i] % P;
	for (int i = 0; i < n * 2 - 1; ++i)
		reverse(q[i].a.begin(), q[i].a.end());
	for (int i = n * 2 - 2; i >= 0; --i)
		if (ls[i])
		p[i] = p[ls[i]] * q[rs[i]] + p[rs[i]] * q[ls[i]];
	return p[0];
	}

} tp;

Poly operator "" _z(unsigned long long a) { return {0, (int) a}; }

Poly operator+(int v, const Poly &rhs) { return Poly(v) + rhs; }

Poly Poly::operator*(const Poly &rhs) const {
	int n = deg(), m = rhs.deg();
	if (n <= 10 || m <= 10 || n + m <= BRUTE_N2_LIMIT) {
	Poly ret = zeroes(n + m);
	for (int i = 0; i <= n; ++i)
		for (int j = 0; j <= m; ++j)
		ret[i + j] = (ret[i + j] + a[i] * (ll) rhs[j]) % P;
	return ret;
	}
	n += m;
	int l = 0;
	while ((1 << l) <= n)
	++l;
	vector<int> res(1 << l), tmp(1 << l);
	memcpy(res.data(), base(), a.size() * sizeof(int));
	ntt.fft(res.data(), l, 1);
	memcpy(tmp.data(), rhs.base(), rhs.a.size() * sizeof(int));
	ntt.fft(tmp.data(), l, 1);
	for (int i = 0; i < (1 << l); ++i)
	res[i] = res[i] * (ll) tmp[i] % P;
	ntt.fft(res.data(), l, -1);
	res.resize(n + 1);
	return res;
}

Poly Poly::inv() const {
	Poly g = nt.inv(a[0]);
	for (int t = 0; (1 << t) <= deg(); ++t)
	nit.inv(slice((2 << t) - 1), g, t);
	g.redeg(deg());
	return g;
}

Poly Poly::taylor(int k) const {
	int n = deg();
	Poly t = zeroes(n);
	simp.check(n);
	for (int i = 0; i <= n; ++i)
	t[n - i] = a[i] * (ll) simp.fac[i] % P;
	int pw = 1;
	Poly help = vector<int>(simp.ifac.begin(), simp.ifac.begin() + n + 1);
	for (int i = 0; i <= n; ++i) {
	help[i] = help[i] * (ll) pw % P;
	pw = pw * (ll) k % P;
	}
	t = t * help;
	for (int i = 0; i <= n; ++i)
	help[i] = t[n - i] * (ll) simp.ifac[i] % P;
	return help;
}

Poly Poly::pow(int k) const {
	if (k == 0)
	return 1;
	if (k == 1)
	return *this;
	int n = deg() * k;
	int lgn = 0;
	while ((1 << lgn) <= n)
	++lgn;
	vector<int> val = a;
	val.resize(1 << lgn);
	ntt.fft(val.data(), lgn, 1);
	for (int i = 0; i < (1 << lgn); ++i)
	val[i] = mpow(val[i], k);
	ntt.fft(val.data(), lgn, -1);
	return val;
}

Poly Poly::der() const {
	if (deg() == 0)
	return 0;
	vector<int> res(deg());
	for (int i = 0; i < deg(); ++i)
	res[i] = a[i + 1] * (ll) (i + 1) % P;
	return res;
}

Poly Poly::integ() const {
	vector<int> res(deg() + 2);
	simp.check(deg() + 1);
	for (int i = 0; i <= deg(); ++i)
	res[i + 1] = a[i] * (ll) simp.inv[i + 1] % P;
	return res;
}

Poly Poly::quo(const Poly &rhs) const {
	if (rhs.deg() == 0)
	return a[0] * (ll) nt.inv(rhs[0]) % P;
	Poly g = nt.inv(rhs[0]);
	int t = 0, n;
	for (n = 1; (n << 1) <= rhs.deg(); ++t, n <<= 1)
	nit.inv(rhs.slice((n << 1) - 1), g, t);
	Poly nttg = g;
	nttg.redeg((n << 1) - 1);
	ntt.fft(nttg.base(), t + 1, 1);
	Poly eps1 = rhs.slice((n << 1) - 1);
	ntt.fft(eps1.base(), t + 1, 1);
	for (int i = 0; i < (n << 1); ++i)
	eps1[i] = eps1[i] * (ll) nttg[i] % P;
	ntt.fft(eps1.base(), t + 1, -1);
	memcpy(eps1.base(), eps1.base() + n, sizeof(int) << t);
	memset(eps1.base() + n, 0, sizeof(int) << t);
	ntt.fft(eps1.base(), t + 1, 1);
	Poly h0 = slice(n - 1);
	h0.redeg((n << 1) - 1);
	ntt.fft(h0.base(), t + 1);
	Poly h0g0 = zeroes((n << 1) - 1);
	for (int i = 0; i < (n << 1); ++i)
	h0g0[i] = h0[i] * (ll) nttg[i] % P;
	ntt.fft(h0g0.base(), t + 1, -1);
	Poly h0eps1 = zeroes((n << 1) - 1);
	for (int i = 0; i < (n << 1); ++i)
	h0eps1[i] = h0[i] * (ll) eps1[i] % P;
	ntt.fft(h0eps1.base(), t + 1, -1);
	for (int i = 0; i < n; ++i) {
	h0eps1[i] = operator[](i + n) - h0eps1[i];
	if (h0eps1[i] < 0)
		h0eps1[i] += P;
	}
	memset(h0eps1.base() + n, 0, sizeof(int) << t);
	ntt.fft(h0eps1.base(), t + 1);
	for (int i = 0; i < (n << 1); ++i)
	h0eps1[i] = h0eps1[i] * (ll) nttg[i] % P;
	ntt.fft(h0eps1.base(), t + 1, -1);
	memcpy(h0eps1.base() + n, h0eps1.base(), sizeof(int) << t);
	memset(h0eps1.base(), 0, sizeof(int) << t);
	return (h0g0 + h0eps1).slice(rhs.deg());
}

Poly Poly::ln() const {
	if (deg() == 0)
	return 0;
	return der().quo(slice(deg() - 1)).integ();
}

pair<Poly, Poly> Poly::sqrti() const {
	Poly g = nt.sqrt(a[0]), h = nt.inv(g[0]), nttg = g;
	for (int t = 0; (1 << t) <= deg(); ++t) {
	nit.sqrt(slice((2 << t) - 1), g, nttg, h, t);
	nttg = g;
	ntt.fft(nttg.base(), t + 1, 1);
	nit.inv(g, nttg, h, t);
	}
	return make_pair(g.slice(deg()), h.slice(deg()));
}

Poly Poly::sqrt() const {
	Poly g = nt.sqrt(a[0]), h = nt.inv(g[0]), nttg = g;
	for (int t = 0; (1 << t) <= deg(); ++t) {
	nit.sqrt(slice((2 << t) - 1), g, nttg, h, t);
	if ((2 << t) <= deg()) {
		nttg = g;
		ntt.fft(nttg.base(), t + 1, 1);
		nit.inv(g, nttg, h, t);
	}
	}
	return g.slice(deg());
}

Poly Poly::exp() const {
	vector<int> der(a), ret(a.size());
	for (int i = 0; i < a.size(); ++i)
	der[i] = der[i] * (ll) i % P;
	src.run(der, ret, [&](int i) {
	if (i == 0) ret[0] = 1;
	else ret[i] = ret[i] * (ll) simp.ginv(i) % P;
	});
	return ret;
}

pair<Poly, Poly> Poly::expi() const {
	Poly g = 1, h = 1, nttg = {1, 1};
	for (int t = 0; (1 << t) <= deg(); ++t) {
	nit.exp(slice((2 << t) - 1), g, nttg, h, t);
	nttg = g;
	nttg.redeg((4 << t) - 1);
	ntt.fft(nttg.base(), t + 2);
	Poly f2n = zeroes((2 << t) - 1);
	for (int i = 0; i < (2 << t); ++i)
		f2n[i] = nttg[i << 1];
	nit.inv(g, f2n, h, t);
	}
	return make_pair(g.slice(deg()), h.slice(deg()));
}

Poly Poly::exp(int k) const {
	int lead, lz = 0;
	while (lz < deg() && !a[lz])
	++lz;
	if (lz == deg() && !a[lz])
	return *this;
	lead = a[lz];
	if (lz * (ll) k > deg())
	return zeroes(deg());
	Poly part = Poly(vector<int>(a.begin() + lz, a.begin() + deg() - lz * (k - 1) + 1)) * nt.inv(lead);
	part = (part.ln() * k).exp() * mpow(lead, k);
	vector<int> ret(deg() + 1);
	memcpy(ret.data() + lz * k, part.base(), sizeof(int) * (deg() - lz * k + 1));
	return ret;
}

Poly Poly::operator/(const Poly &rhs) const {
	int n = deg(), m = rhs.deg();
	if (n < m)
	return 0;
	Poly ta(vector<int>(a.rbegin(), a.rend())),
			tb(vector<int>(rhs.a.rbegin(), rhs.a.rend()));
	ta.redeg(n - m);
	tb.redeg(n - m);
	Poly q = ta.quo(tb);
	reverse(q.a.begin(), q.a.end());
	return q;
}

pair<Poly, Poly> Poly::div(const Poly &rhs) const {
	if (deg() < rhs.deg())
	return make_pair(0, *this);
	int n = deg(), m = rhs.deg();
	Poly q = operator/(rhs), r;
	int lgn = 0;
	while ((1 << lgn) < rhs.deg())
	++lgn;
	int t = (1 << lgn) - 1;
	r = zeroes(t);
	Poly tmp = zeroes(t);
	for (int i = 0; i <= m; ++i)
	if ((r[i & t] += rhs[i]) >= P)
		r[i & t] -= P;
	for (int i = 0; i <= n - m; ++i)
	if ((tmp[i & t] += q[i]) >= P)
		tmp[i & t] -= P;
	ntt.fft(r.base(), lgn, 1);
	ntt.fft(tmp.base(), lgn, 1);
	for (int i = 0; i <= t; ++i)
	tmp[i] = tmp[i] * (ll) r[i] % P;
	ntt.fft(tmp.base(), lgn, -1);
	memset(r.base(), 0, sizeof(int) << lgn);
	for (int i = 0; i <= n; ++i)
	if ((r[i & t] += a[i]) >= P)
		r[i & t] -= P;
	for (int i = 0; i < m; ++i)
	if ((r[i] -= tmp[i]) < 0)
		r[i] += P;
	return make_pair(q, r.slice(m - 1));
}

Poly Poly::operator%(const Poly &rhs) const {
	if (deg() < rhs.deg())
	return *this;
	return div(rhs).second;
}
/*
_/_/_/_/    _/_/_/_/_/  _/_/_/
_/      _/      _/    _/      _/
_/      _/      _/    _/      _/
_/      _/      _/    _/      _/
_/      _/      _/    _/  _/  _/
_/      _/  _/  _/    _/    _/_/
_/_/_/_/      _/_/     _/_/_/_/_/

_/_/_/_/    _/    _/  _/      _/
_/      _/   _/  _/   _/_/  _/_/
_/      _/    _/_/    _/ _/_/ _/
_/      _/     _/     _/  _/  _/
_/      _/    _/_/    _/      _/
_/      _/   _/  _/   _/      _/
_/_/_/_/    _/    _/  _/      _/

_/_/_/_/_/ _/_/_/_/_/ _/_/_/_/_/
	_/         _/     _/
	_/         _/     _/
	_/         _/     _/_/_/_/
	_/         _/     _/
	_/         _/     _/
	_/     _/_/_/_/_/ _/_/_/_/_/

_/_/_/_/_/ _/_/_/_/_/ _/_/_/_/_/
	_/         _/     _/
	_/         _/     _/
	_/         _/     _/_/_/_/
	_/         _/     _/
	_/         _/     _/
	_/     _/_/_/_/_/ _/_/_/_/_/
*/
#include <cassert>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cctype>

#include <algorithm>
#include <random>
#include <bitset>
#include <queue>
#include <functional>
#include <set>
#include <map>
#include <vector>
#include <chrono>
#include <iostream>
#include <iomanip>
#include <limits>
#include <numeric>

#define LOG(FMT...) fprintf(stderr, FMT)

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

template <class T>
istream& operator>>(istream& is, vector<T>& v) {
	for (T& x : v)
	is >> x;
	return is;
}

template <class T>
ostream& operator<<(ostream& os, const vector<T>& v) {
	if (!v.empty()) {
	os << v.front();
	for (int i = 1; i < v.size(); ++i)
		os << ' ' << v[i];
	}
	return os;
}

Poly solve(int t, int n, int a) {
	Poly ret = zeroes(t);
	function<void(int, int, Poly)> solve = [&](int l, int r, Poly pol) {
	if (l == r) {
		ret[l] = pol[0];
		return;
	}
	int mid = (l + r) / 2;
	Poly mul = zeroes((mid + 1 - l) * 2);
	for (int i = 0; i <= mid + 1 - l; ++i) mul[i * 2] = simp.binom(mid + 1 - l, i);
	solve(mid + 1, r, tp.mul(pol, mul));
	Poly le = zeroes((mid - l) * 2);
	for (int i = -(mid - l); i <= (mid - l); ++i)
		le[(mid - l) + i] = pol[(r - l) + i];
	solve(l, mid, le);
	};
	Poly coe = zeroes(t * 2);
	int c = 1;
	for (int i = a; i <= a + t; ++i) {
	if (i % (n + 1) == 0) {
		c = P - c;
		continue;
	}
	coe[i - a + t] = c;
	}
	c = 1;
	for (int i = a - 1; i >= a - t; --i) {
	if (i % (n + 1) == 0) {
		c = P - c;
		continue;
	}
	coe[i - a + t] = c;
	}
	//coe.println(stderr);
	solve(0, t, coe);
	//ret.println(stderr);
	return ret;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int d, n, m, k, a, b, c; cin >> d >> n >> m >> k >> a >> b >> c;
	auto u = solve(d, n, a), v = solve(d, m, b), w = solve(d, k, c);
	for (int i = 0; i <= d; ++i) {
		u[i] = u[i] * (ull)simp.gifac(i) % P;
		v[i] = v[i] * (ull)simp.gifac(i) % P;
		w[i] = w[i] * (ull)simp.gifac(i) % P;
	}
	u = u * v;
	int ans = 0; for (int i = 0; i <= d; ++i) ans = (ans + u[i] * (ull)w[d - i]) % P;
	ans = ans * (ull)simp.gfac(d) % P;
	std::cout << ans << '\n';

	return 0;
}

详细

Subtask #1:

score: 5
Accepted

Test #1:

score: 5
Accepted
time: 1ms
memory: 3668kb

input:

50 41 46 42 8 20 21

output:

791406134

result:

ok 1 number(s): "791406134"

Test #2:

score: 5
Accepted
time: 0ms
memory: 3756kb

input:

50 49 44 48 49 15 25

output:

544847893

result:

ok 1 number(s): "544847893"

Subtask #2:

score: 10
Accepted

Dependency #1:

100%
Accepted

Test #3:

score: 10
Accepted
time: 23ms
memory: 4076kb

input:

5000 4994 4990 4990 976 2257 2505

output:

836390717

result:

ok 1 number(s): "836390717"

Test #4:

score: 10
Accepted
time: 23ms
memory: 4320kb

input:

5000 4994 4997 4994 4399 1826 1332

output:

65414465

result:

ok 1 number(s): "65414465"

Subtask #3:

score: 15
Accepted

Test #5:

score: 15
Accepted
time: 616ms
memory: 14264kb

input:

120000 300 1 1 141 1 1

output:

637174

result:

ok 1 number(s): "637174"

Test #6:

score: 15
Accepted
time: 617ms
memory: 14308kb

input:

120000 994 1 1 15 1 1

output:

218803691

result:

ok 1 number(s): "218803691"

Test #7:

score: 15
Accepted
time: 615ms
memory: 14376kb

input:

120000 119999 1 1 19896 1 1

output:

68846585

result:

ok 1 number(s): "68846585"

Subtask #4:

score: 10
Accepted

Test #8:

score: 10
Accepted
time: 618ms
memory: 14216kb

input:

119000 119991 119991 1 23819 52139 1

output:

944500934

result:

ok 1 number(s): "944500934"

Subtask #5:

score: 15
Accepted

Dependency #4:

100%
Accepted

Test #9:

score: 15
Accepted
time: 616ms
memory: 14168kb

input:

120000 13997 13996 1 42 9266 1

output:

775637357

result:

ok 1 number(s): "775637357"

Test #10:

score: 15
Accepted
time: 615ms
memory: 14216kb

input:

120000 13997 13997 1 9768 6131 1

output:

151873213

result:

ok 1 number(s): "151873213"

Subtask #6:

score: 35
Accepted

Dependency #3:

100%
Accepted

Dependency #5:

100%
Accepted

Test #11:

score: 35
Accepted
time: 618ms
memory: 14192kb

input:

120000 294 296 1 142 273 1

output:

889786082

result:

ok 1 number(s): "889786082"

Test #12:

score: 35
Accepted
time: 604ms
memory: 14216kb

input:

120000 395 390 1 370 185 1

output:

884557050

result:

ok 1 number(s): "884557050"

Test #13:

score: 35
Accepted
time: 619ms
memory: 14356kb

input:

120000 491 495 1 430 25 1

output:

272929924

result:

ok 1 number(s): "272929924"

Test #14:

score: 35
Accepted
time: 618ms
memory: 14292kb

input:

120000 590 593 1 418 459 1

output:

446962505

result:

ok 1 number(s): "446962505"

Test #15:

score: 35
Accepted
time: 619ms
memory: 14352kb

input:

120000 697 690 1 166 450 1

output:

216092107

result:

ok 1 number(s): "216092107"

Test #16:

score: 35
Accepted
time: 605ms
memory: 14284kb

input:

120000 793 799 1 416 61 1

output:

661260042

result:

ok 1 number(s): "661260042"

Test #17:

score: 35
Accepted
time: 612ms
memory: 14160kb

input:

120000 1000 1000 1 613 547 1

output:

429669083

result:

ok 1 number(s): "429669083"

Test #18:

score: 35
Accepted
time: 622ms
memory: 14236kb

input:

120000 1993 1995 1 493 565 1

output:

609392900

result:

ok 1 number(s): "609392900"

Test #19:

score: 35
Accepted
time: 631ms
memory: 14256kb

input:

120000 4995 4998 1 3166 3765 1

output:

394497547

result:

ok 1 number(s): "394497547"

Test #20:

score: 35
Accepted
time: 620ms
memory: 14236kb

input:

120000 9994 9991 1 6099 691 1

output:

795651799

result:

ok 1 number(s): "795651799"

Test #21:

score: 35
Accepted
time: 618ms
memory: 14296kb

input:

120000 49990 49990 1 41933 2862 1

output:

360787513

result:

ok 1 number(s): "360787513"

Test #22:

score: 35
Accepted
time: 615ms
memory: 14284kb

input:

120000 119996 119994 1 58014 49559 1

output:

682979057

result:

ok 1 number(s): "682979057"

Subtask #7:

score: 10
Accepted

Dependency #1:

100%
Accepted

Dependency #2:

100%
Accepted

Dependency #3:

100%
Accepted

Dependency #4:

100%
Accepted

Dependency #5:

100%
Accepted

Dependency #6:

100%
Accepted

Test #23:

score: 10
Accepted
time: 611ms
memory: 14204kb

input:

120000 296 300 297 89 130 280

output:

702788425

result:

ok 1 number(s): "702788425"

Test #24:

score: 10
Accepted
time: 622ms
memory: 14376kb

input:

120000 392 397 391 222 280 10

output:

322470184

result:

ok 1 number(s): "322470184"

Test #25:

score: 10
Accepted
time: 616ms
memory: 14240kb

input:

120000 499 498 500 263 315 367

output:

449848666

result:

ok 1 number(s): "449848666"

Test #26:

score: 10
Accepted
time: 611ms
memory: 14308kb

input:

120000 598 591 594 497 474 400

output:

35486519

result:

ok 1 number(s): "35486519"

Test #27:

score: 10
Accepted
time: 626ms
memory: 14192kb

input:

120000 694 692 695 625 173 477

output:

785203749

result:

ok 1 number(s): "785203749"

Test #28:

score: 10
Accepted
time: 609ms
memory: 14220kb

input:

120000 794 796 800 395 465 507

output:

897269426

result:

ok 1 number(s): "897269426"

Test #29:

score: 10
Accepted
time: 619ms
memory: 14372kb

input:

120000 993 998 991 196 712 911

output:

464727191

result:

ok 1 number(s): "464727191"

Test #30:

score: 10
Accepted
time: 613ms
memory: 14352kb

input:

120000 1991 2000 1994 1937 1362 1494

output:

473701811

result:

ok 1 number(s): "473701811"

Test #31:

score: 10
Accepted
time: 626ms
memory: 14288kb

input:

120000 4994 4990 4990 646 1214 2276

output:

763540821

result:

ok 1 number(s): "763540821"

Test #32:

score: 10
Accepted
time: 622ms
memory: 14220kb

input:

120000 9994 9992 9991 6588 9538 2632

output:

804858722

result:

ok 1 number(s): "804858722"

Test #33:

score: 10
Accepted
time: 622ms
memory: 14236kb

input:

120000 49997 49997 49993 46278 44140 26931

output:

139550295

result:

ok 1 number(s): "139550295"

Test #34:

score: 10
Accepted
time: 617ms
memory: 14304kb

input:

120000 119997 120000 120000 24867 116477 35338

output:

946147605

result:

ok 1 number(s): "946147605"