萌新求助如何卡常
查看原帖
萌新求助如何卡常
448887
cancan123456楼主2022/4/26 20:49
#include <cstdio>
#include <vector>
using namespace std;
typedef long long ll;
const ll mod = 998244353, g = 3;
ll pow(ll a, ll b) {
	ll ans = 1;
	while (b != 0) {
		if ((b & 1) == 1) {
			ans = ans * a % mod;
		}
		a = a * a % mod;
		b = b / 2;
	}
	return ans;
}
void swap(ll & a, ll & b) {
	a ^= b ^= a ^= b;
}
class Poly {
	private:
		vector < ll > rev;
		void get_rev() {
			rev.resize(n);
			rev[0] = 0;
			for (int i = 0; i < n; i++) {
				rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (len - 1));
			}
		}
	public:
		vector < ll > a;
		int len, n;
		Poly() {
			len = 0;
			n = 1;
			a.push_back(0);
			get_rev();
		}
		void set_length(int len_, bool clear = false) {
			if (clear) {
				a.resize(1 << len_);
			} else {
				if (len < len_) {
					a.insert(a.end(), (1 << len_) - n, 0);
				} else {
					a.erase(a.begin() + (1 << len_), a.end());
				}
			}
			n = 1 << len_;
			len = len_;
			get_rev();
		}
		ll & operator [] (const int & i) {
			return a[i];
		}
		ll operator [] (const int & i) const {
			return a[i];
		}
		void NTT(int inv) {
			for (int i = 0; i < n; i++) {
				if (rev[i] < i) {
					swap(a[i], a[rev[i]]);
				}
			}
			for (int mid = 1; mid < n; mid <<= 1) {
				ll omega = pow(g, (mod - 1) / (2 * mid));
				if (inv == -1) {
					omega = pow(omega, mod - 2);
				}
				for (int i = 0; i < n; i += 2 * mid) {
					ll w = 1;
					for (int j = 0; j < mid; j++, w = w * omega % mod) {
						ll x = a[i + j];
						ll y = a[i + mid + j] * w % mod;
						a[i + j] = (x + y) % mod;
						a[i + mid + j] = (x - y + mod) % mod;
					}
				}
			}
			if (inv == -1) {
				ll inv_n = pow(n, mod - 2);
				for (int i = 0; i < n; i++) {
					a[i] = a[i] * inv_n % mod;
				}
			}
		}
};
void print(const Poly & a) {
	for (int i = 0; i < a.n; i++) {
		printf("%lld ", a[i]);
	}
	putchar(10);
}
Poly set_length(const Poly & a, const int & len) {
	static Poly b;
	b = a;
	b.set_length(len);
	return b;
}
void unify_length(const Poly & a, const Poly & b, Poly & x, Poly & y, Poly & c) {
	x = a;
	x.set_length(max(a.len, b.len));
	y = b;
	y.set_length(max(a.len, b.len));
	c.set_length(max(a.len, b.len), true);
}
Poly Add(const Poly & a, const Poly & b) {
	static Poly x, y, c;
	unify_length(a, b, x, y, c);
	for (int i = 0; i < x.n; i++) {
		c[i] = (x[i] + y[i]) % mod;
	}
	return c;
}
Poly Sub(const Poly & a, const Poly & b) {
	static Poly x, y, c;
	unify_length(a, b, x, y, c);
	for (int i = 0; i < x.n; i++) {
		c[i] = (x[i] - y[i] + mod) % mod;
	}
	return c;
}
Poly Mult(const Poly & a, const ll & b) {
	static Poly c;
	c = a;
	for (int i = 0; i < c.n; i++) {
		c[i] = c[i] * b % mod;
	}
	return c;
}
Poly Mult(const ll & b, const Poly & a) {
	static Poly c;
	c = a;
	for (int i = 0; i < c.n; i++) {
		c[i] = c[i] * b % mod;
	}
	return c;
}
Poly Mult(const Poly & a, const Poly & b) {
	static Poly x, y, c;
	unify_length(a, b, x, y, c);
	x.set_length(x.len + 1);
	y.set_length(y.len + 1);
	c.set_length(c.len + 1);
	x.NTT(1);
	y.NTT(1);
	for (int i = 0; i < x.n; i++) {
		c[i] = x[i] * y[i] % mod;
	}
	c.NTT(-1);
	return c;
}
Poly MultMod(const Poly & a, const Poly & b) {
	static Poly c;
	c = Mult(a, b);
	c.set_length(c.len - 1);
	return c;
}
Poly Inverse(const Poly & a) {
	static Poly ans[2];
	ans[0].set_length(0);
	ans[0][0] = pow(a[0], mod - 2);
	for (int i = 1, t; i <= a.len; i++) {
		t = i & 1;
		ans[t] = Sub(Mult(ans[t ^ 1], 2), MultMod(Mult(ans[t ^ 1], ans[t ^ 1]), set_length(a, i)));
	}
	return ans[a.len & 1];
}
Poly Differential(const Poly & a) {
	static Poly b;
	b.set_length(a.len);
	for (int i = a.n - 1; i > 0; i--) {
		b[i - 1] = a[i] * i % mod;
	}
	return b;
}
Poly Integral(const Poly & a) {
	static Poly b;
	b.set_length(a.len);
	for (int i = 1; i < a.n; i++) {
		b[i] = a[i - 1] * pow(i, mod - 2) % mod;
	}
	return b;
}
Poly Natural_Log(const Poly & a) {
	return Integral(MultMod(Differential(a), Inverse(a)));
}
Poly Exp(const Poly & a) {
	static Poly ans[2], one;
	ans[0].set_length(0);
	ans[0][0] = 1;
	for (int i = 1, t; i <= a.len; i++) {
		t = i & 1;
		ans[t ^ 1].set_length(i);
		one.set_length(i);
		one[0] = 1;
		ans[t] = Mult(ans[t ^ 1], Add(Sub(one, Natural_Log(ans[t ^ 1])), a));
	}
	return ans[a.len & 1];
}
Poly __Power(const Poly & a, const ll & k) {
	return Exp(Mult(Natural_Log(a), k));
}
Poly Power(const Poly & a, const ll & k0, const ll & k1, const ll & k2) {
	static Poly temp, one;
	int t = -1;
	ll b;
	for (int i = 0; i < a.n; i++) {
		if (a[i] != 0) {
			t = i;
			b = a[i];
			break;
		}
	}
	if (t * k2 >= a.n || t == -1) {
		one.set_length(a.len);
		return one;
	}
	temp = a;
	for (int i = t; i < temp.n; i++) {
		temp[i - t] = temp[i];
	}
	for (int i = temp.n - t; i < temp.n; i++) {
		temp[i] = 0;
	}
	ll inv_b = pow(b, mod - 2);
	for (int i = 0; i < temp.n; i++) {
		temp[i] = temp[i] * inv_b % mod;
	}
	temp = __Power(temp, k0);
	ll b_k = pow(b, k1);
	for (int i = 0; i < temp.n; i++) {
		temp[i] = temp[i] * b_k % mod;
	}
	for (int i = temp.n - t * k0 - 1; i >= 0; i--) {
		temp[i + t * k0] = temp[i];
	}
	for (int i = 0; i < t * k0 && i < temp.n; i++) {
		temp[i] = 0;
	}
	return temp;
}
int get_length(int n) {
	for (int i = 0; ; i++) {
		if (n <= (1 << i)) {
			return i;
		}
	}
}
int main() {
	Poly a;
	int n;
	scanf("%d", &n);
	ll k0 = 0, k1 = 0, k2 = 0;
	int c;
	do {
		c = getchar();
	} while ('0' > c || c > '9');
	do {
		k0 = ((k0 * 10) + (c ^ 48)) % mod;
		k1 = ((k1 * 10) + (c ^ 48)) % (mod - 1);
		if ((k2 * 10) + (c ^ 48) <= mod) {
			k2 = (k2 * 10) + (c ^ 48);
		}
		c = getchar();
	} while ('0' <= c && c <= '9');
	a.set_length(get_length(n));
	for (int i = 0; i < n; i++) {
		scanf("%lld", &a[i]);
	}
	Poly b;
	b = Power(a, k0, k1, k2);
	for (int i = 0; i < n; i++) {
		printf("%lld ", b[i]);
	}
	return 0;
}

不想用数组写,有人用 vector 过了吗?

2022/4/26 20:49
加载中...