[ural 2125]. Continue the Sequence && [loj 166]. 拉格朗日插值 2

题意

略。

题解

果然是一道板题。我连板题都不会
以下实际上是ural那题的题解。
考虑如果直接用拉格朗日插值,复杂度是(mathcal O(n ^ 2))的。
但是这道题要求求点值的(x)很平凡(都是离散的且连着的整数),所以考虑将答案形式化。
考虑我们知道的是(f_0, f_1, ldots, f_n)(平移一下),要求的是(f_{n + 1}, f_{n + 2}, ldots, f_{n + m})

[egin{aligned} f(n + i) & = sum_{j = 0} ^ n f(j) frac{prod_{k != j} (n + i - k)}{prod_{k != j} (j - k)} \ & = sum_{j = 0} ^ n f(j) frac{(n + i)(n + i - 1) ldots (n - i - (j - 1)(n - i - (j + 1)) ldots (n + i - n)}{j(j - 1) ldots (j - (j - 1))(j - (j + 1)) ldots (j - n)} \ & = frac{(n + i)!}{(n + i - n - 1)!} sum_{j = 0} ^ n f(j) frac{{(-1)} ^ {n - j}}{j! (n - j)!} frac{1}{n + i - j} \ end{aligned} ]

(g(i) = f(i) frac{{(-1)} ^ {n - i}}{i! (n - i)!}, h(i) = frac{1}{i}),则

[f(n + i) = frac{(n + i)!}{(i - 1)!} sum_{j = 0} ^ n g(j) h(n + i - j) \ ]

然后一个卷积就没了。复杂度(mathcal O((n + m) log (n + m)))

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef vector <int> poly;
const int N = 1 << 21, mod = 998244353, G = 3;
const ll infty = 1ll * mod * mod;
int power (int x, int y) {
	int ret = 1;
	y < 0 ? y += mod - 1 : 0;
	for ( ; y; y >>= 1, x = 1ll * x * x % mod) {
		if (y & 1) {
			ret = 1ll * ret * x % mod;
		}
	}
	return ret;
}
namespace {
	int adjust (int n) {
		int ret = 1;
		for ( ; ret < n; ret <<= 1);
		return ret;
	}
	poly trans (int n, int *a) {
		int m = adjust(n);
		poly ret; ret.resize(m, 0);
		for (int i = 0; i < n; ++i) {
			ret[i] = a[i];
		}
		return ret;
	}
	void dnt (int n, poly &_a, int sgn) {
		static int rev[N], a[N], wi[N];
		for (int i = 0; i < n; ++i) {
			rev[i] = (rev[i >> 1] >> 1) | (i & 1 ? n >> 1 : 0);
			a[i] = _a[rev[i]];
		}
		for (int l = 2, _w; l <= n; l <<= 1) {
			_w = power(G, (mod - 1) / l * sgn), wi[l >> 1] = 1;
			for (int i = (l >> 1) + 1; i < l; ++i) {
				wi[i] = 1ll * wi[i - 1] * _w % mod;
			}
		}
		for (int l = 2, m = 1; l <= n; m = l, l <<= 1) {
			for (int i = 0; i < n; i += l) {
				int *u = a + i, *v = a + i + m, *w = wi + m;
				for (int j = 0, x, y; j < m; ++u, ++v, ++w, ++j) {
					x = *u, y = 1ll * (*v) * (*w) % mod;
					*u = (x + y) % mod, *v = (x - y + mod) % mod;
				}
			}
		}
		int coe = power(n, sgn > 0 ? 0 : -1);
		for (int i = 0; i < n; ++i) {
			_a[i] = 1ll * a[i] * coe % mod;
		}
	}
	poly conv (int n, poly a, poly b) {
		n <<= 1, a.resize(n, 0), b.resize(n, 0);
		dnt(n, a, 1), dnt(n, b, 1);
		for (int i = 0; i < n; ++i) {
			a[i] = 1ll * a[i] * b[i] % mod;
		}
		dnt(n, a, -1);
		return a;
	}
}
poly A, B, C;
int n, m, ans;
int a[N], b[N], fac[N], ivf[N], _fac[N], _ivf[N];
void prework () {
	fac[0] = 1;
	for (int i = 1; i <= n + m + 1; ++i) {
		fac[i] = 1ll * fac[i - 1] * i % mod;
	}
	ivf[n + m + 1] = power(fac[n + m + 1], mod - 2);
	for (int i = n + m; ~i; --i) {
		ivf[i] = 1ll * ivf[i + 1] * (i + 1) % mod;
	}
}
int main () {
	scanf("%d%d", &n, &m), --n, prework();
	for (int i = 0; i <= n; ++i) {
		scanf("%d", &a[i]);
		a[i] = 1ll * a[i] * ivf[i] % mod * ivf[n - i] % mod;
		a[i] = ((n - i) & 1 ? mod - a[i] : a[i]);
	}
	for (int i = 0; i <= n + m; ++i) {
		b[i] = power(i, mod - 2);
	}
	A = trans(n + m + 1, a), B = trans(n + m + 1, b);
	C = conv(A.size(), A, B);
	for (int i = n + 1; i <= n + m; ++i) {
		ans = 1ll * fac[i] * ivf[i - n - 1] % mod * C[i] % mod;
		printf("%d ", ans);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/psimonw/p/11801023.html