[洛谷P4721]【模板】分治 FFT_求逆

题目大意:给定长度为$n-1$的数组$g_{[1,n)}$,求$f_{[0,n)}$,要求:

$$
f_i=sum_{j=1}^if_{i-j}g_j\
f_0=1
$$

题解:分治$FFT$博客,发现这道题就是求$f*g=f-1$($f-1$就是没有常数项的$f$),改写一下式子:
$$
f*gequiv f-1pmod{x^n}\
f-f*gequiv1pmod{x^n}\
f*(1-g)equiv1pmod{x^n}\
fequiv(1-g)^{-1}pmod{x^n}
$$


卡点:

C++ Code:

#include <algorithm>
#include <cstdio>
#include <cctype>
namespace std {
	struct istream {
#define M (1 << 21 | 3)
		char buf[M], *ch = buf - 1;
		inline istream() {
#ifndef ONLINE_JUDGE
			freopen("input.txt", "r", stdin);
#endif
			fread(buf, 1, M, stdin);
		}
		inline istream& operator >> (int &x) {
			while (isspace(*++ch));
			for (x = *ch & 15; isdigit(*++ch); ) x = x * 10 + (*ch & 15);
			return *this;
		}
#undef M
	} cin;
	struct ostream {
#define M (1 << 21 | 3)
		char buf[M], *ch = buf - 1;
		int w;
		inline ostream& operator << (int x) {
			if (!x) {
				*++ch = '0';
				return *this;
			}
			for (w = 1; w <= x; w *= 10);
			for (w /= 10; w; w /= 10) *++ch = (x / w) ^ 48, x %= w;
			return *this;
		}
		inline ostream& operator << (const char x) {*++ch = x; return *this;}
		inline ~ostream() {
#ifndef ONLINE_JUDGE
			freopen("output.txt", "w", stdout);
#endif
			fwrite(buf, 1, ch - buf + 1, stdout);
		}
#undef M
	} cout;
}

const int mod = 998244353, G = 3;
namespace Math {
	inline int pw(int base, int p) {
		static int res;
		for (res = 1; p; p >>= 1, base = static_cast<long long> (base) * base % mod) if (p & 1) res = static_cast<long long> (res) * base % mod;
		return res;
	}
	inline int inv(int x) {return pw(x, mod - 2);}
}

inline void reduce(int &a) {a += a >> 31 & mod;}
inline long long get_reducell(long long a) {return a += a >> 63 & mod;}
namespace Poly {
#define N (262144 | 3)
	int lim, ilim, s, rev[N];
	int Wn[N + 1];
	inline void init(int n) {
		s = -1, lim = 1; while (lim <= n) lim <<= 1, s++; ilim = Math::inv(lim);
		for (register int i = 1; i < lim; i++) rev[i] = rev[i >> 1] >> 1 | (i & 1) << s;
		const int t = Math::pw(G, (mod - 1) / lim);
		*Wn = 1; for (register int *i = Wn; i != Wn + lim; ++i) *(i + 1) = static_cast<long long> (*i) * t % mod;
	}
	inline void clear(register int *l, const int *r) {
		if (l >= r) return ;
		while (l != r) *l++ = 0;
	}

	inline void NTT(int *A, const int op = 1) {
		for (register int i = 1; i < lim; i++) if (i < rev[i]) std::swap(A[i], A[rev[i]]);
		for (register int mid = 1; mid < lim; mid <<= 1) {
			const int t = lim / mid >> 1;
			for (register int i = 0; i < lim; i += mid << 1) {
				for (register int j = 0; j < mid; j++) {
					const int W = op ? Wn[t * j] : Wn[lim - t * j];
					const int X = A[i + j], Y = static_cast<long long> (A[i + j + mid]) * W % mod;
					reduce(A[i + j] += Y - mod), reduce(A[i + j + mid] = X - Y);
				}
			}
		}
		if (!op) for (register int *i = A; i != A + lim; ++i) *i = static_cast<long long> (*i) * ilim % mod;
	}

	int C[N];
	void INV(int *A, int *B, int n) {
		if (n == 1) {*B = Math::inv(*A); return ;}
		INV(A, B, n + 1 >> 1);
		init(n + n - 1);
		std::copy(A, A + n, C); clear(C + n, C + lim);
		NTT(B), NTT(C);
		for (register int i = 0; i < lim; i++) B[i] = (2 - static_cast<long long> (B[i]) * C[i] % mod + mod) % mod * B[i] % mod;
		NTT(B, 0), clear(B + n, B + lim);
	}
#undef N
}

#define maxn (262144 | 3)
int n, f[maxn], g[maxn];

int main() {
	std::cin >> n;
	*g = 1;
	for (int i = 1; i < n; i++) {
		std::cin >> g[i];
		g[i] = mod - g[i];
	}
	Poly::INV(g, f, n);
	for (int i = 0; i < n; i++) std::cout << f[i] << ' ';
	std::cout << '
';
	return 0;
}

  

原文地址:https://www.cnblogs.com/Memory-of-winter/p/10133416.html