【省内训练2018-11-23】Bishop
生活随笔
收集整理的這篇文章主要介紹了
【省内训练2018-11-23】Bishop
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
【思路要點】
- 先考慮一個子問題,在 N?NN*NN?N 棋盤的主對角線及其右下方放置 KKK 個不能互相攻擊的車,求方案數(shù) f(N,k)f(N,k)f(N,k)。考慮最后一行的放置情況,有遞推式 f(N,k)=f(N?1,k)+(N?k+1)?f(N?1,k?1)f(N,k)=f(N-1,k)+(N-k+1)*f(N-1,k-1)f(N,k)=f(N?1,k)+(N?k+1)?f(N?1,k?1) 。觀察該遞推式的形式,不難發(fā)現(xiàn)其實際上等于第二類斯特林?jǐn)?shù) S(N+1,N+1?k)S(N+1,N+1-k)S(N+1,N+1?k) 。
- 在本題中,首先,象的移動方式不會改變坐標(biāo) (x,y)(x,y)(x,y) 對應(yīng)的 x+yx+yx+y 的奇偶性,我們可以將這兩類坐標(biāo)分開處理,再將結(jié)果卷積起來,得到答案。
- 考慮 x+yx+yx+y 為偶數(shù)的坐標(biāo),我們將棋盤旋轉(zhuǎn) 454545 度,我們得到了一個類似于上述子問題的問題形式,每一行可以放入車的方格數(shù)為 1,1,3,3,5,5,7,7,...1,1,3,3,5,5,7,7,...1,1,3,3,5,5,7,7,... ,換而言之,偶數(shù)行的主對角線上是不允許放入棋子的。
- 考慮對這條新加入的限制進(jìn)行容斥,記 M=?N2?M=\lfloor\frac{N}{2}\rfloorM=?2N?? ,新問題的方案數(shù)為 g(N,K)g(N,K)g(N,K) 。枚舉強制放入棋子的方格數(shù) iii ,則有 g(N,k)=∑i=0M(?1)i(Mi)S(N?i+1,N?k+1)g(N,k)=\sum_{i=0}^{M}(-1)^i\binom{M}{i}S(N-i+1,N-k+1)g(N,k)=∑i=0M?(?1)i(iM?)S(N?i+1,N?k+1) 。
- 展開斯特林?jǐn)?shù),有 g(N,k)=∑i=0M(?1)i(Mi)1(N?k?1)!∑j=0N?k+1(?1)N?k+1?j(N?k+1j)jN?i+1g(N,k)=\sum_{i=0}^{M}(-1)^i\binom{M}{i}\frac{1}{(N-k-1)!}\sum_{j=0}^{N-k+1}(-1)^{N-k+1-j}\binom{N-k+1}{j}j^{N-i+1}g(N,k)=∑i=0M?(?1)i(iM?)(N?k?1)!1?∑j=0N?k+1?(?1)N?k+1?j(jN?k+1?)jN?i+1 。
- 交換求和順序,有 g(N,k)=1(N?k?1)!∑j=0N?k+1(?1)N?k+1?j(N?k+1j)∑i=0M(?1)i(Mi)jN?i+1g(N,k)=\frac{1}{(N-k-1)!}\sum_{j=0}^{N-k+1}(-1)^{N-k+1-j}\binom{N-k+1}{j}\sum_{i=0}^{M}(-1)^{i}\binom{M}{i}j^{N-i+1}g(N,k)=(N?k?1)!1?∑j=0N?k+1?(?1)N?k+1?j(jN?k+1?)∑i=0M?(?1)i(iM?)jN?i+1 。
- 由二項式定理,有 g(N,k)=1(N?k?1)!∑j=0N?k+1(?1)N?k+1?j(N?k+1j)(j?1)MjN?M+1g(N,k)=\frac{1}{(N-k-1)!}\sum_{j=0}^{N-k+1}(-1)^{N-k+1-j}\binom{N-k+1}{j}(j-1)^Mj^{N-M+1}g(N,k)=(N?k?1)!1?∑j=0N?k+1?(?1)N?k+1?j(jN?k+1?)(j?1)MjN?M+1 。
- NTTNTTNTT 對其卷積即可,時間復(fù)雜度 O(NLogN)O(NLogN)O(NLogN) 。
【代碼】
#include<bits/stdc++.h> using namespace std; const int MAXN = 262144; const int P = 998244353; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) {x = 0; int f = 1;char c = getchar();for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';x *= f; } template <typename T> void write(T x) {if (x < 0) x = -x, putchar('-');if (x > 9) write(x / 10);putchar(x % 10 + '0'); } template <typename T> void writeln(T x) {write(x);puts(""); } namespace NTT {const int MAXN = 262144;const int P = 998244353;const int G = 3;int power(int x, int y) {if (y == 0) return 1;int tmp = power(x, y / 2);if (y % 2 == 0) return 1ll * tmp * tmp % P;else return 1ll * tmp * tmp % P * x % P;}int N, Log, home[MAXN];void NTTinit() {for (int i = 0; i < N; i++) {int ans = 0, tmp = i;for (int j = 1; j <= Log; j++) {ans <<= 1;ans += tmp & 1;tmp >>= 1;}home[i] = ans;}}void NTT(int *a, int mode) {for (int i = 0; i < N; i++)if (home[i] < i) swap(a[i], a[home[i]]);for (int len = 2; len <= N; len <<= 1) {int delta;if (mode == 1) delta = power(G, (P - 1) / len);else delta = power(G, P - 1 - (P - 1) / len);for (int i = 0; i < N; i += len) {int now = 1;for (int j = i, k = i + len / 2; k < i + len; j++, k++) {int tmp = a[j];int tnp = 1ll * a[k] * now % P;a[j] = (tmp + tnp) % P;a[k] = (tmp - tnp + P) % P;now = 1ll * now * delta % P;}}}if (mode == -1) {int inv = power(N, P - 2);for (int i = 0; i < N; i++)a[i] = 1ll * a[i] * inv % P;}}void times(int *a, int *b, int *c, int limit) {N = 1, Log = 0;while (N < 2 * limit) {N <<= 1;Log++;}for (int i = limit; i < N; i++)a[i] = b[i] = 0;NTTinit();NTT(a, 1);NTT(b, 1);for (int i = 0; i < N; i++)c[i] = 1ll * a[i] * b[i] % P;NTT(c, -1);} } int power(int x, int y) {if (y == 0) return 1;int tmp = power(x, y / 2);if (y % 2 == 0) return 1ll * tmp * tmp % P;else return 1ll * tmp * tmp % P * x % P; } int fac[MAXN], inv[MAXN]; int odd[MAXN], even[MAXN], res[MAXN]; void update(int &x, int y) {x += y;if (x >= P) x -= P; } void init(int n) {fac[0] = 1;for (int i = 1; i <= n; i++)fac[i] = 1ll * fac[i - 1] * i % P;inv[n] = power(fac[n], P - 2);for (int i = n - 1; i >= 0; i--)inv[i] = inv[i + 1] * (i + 1ll) % P; } void getans(int n, int *res) {static int a[MAXN], b[MAXN];memset(a, 0, sizeof(a));memset(b, 0, sizeof(b));int m = n / 2;for (int i = 0; i <= n + 1; i++) {a[i] = 1ll * inv[i] * power(i, n - m + 1) % P * power((i - 1 + P) % P, m) % P;b[i] = 1ll * inv[i] * power(P - 1, i) % P;}static int c[MAXN];NTT :: times(a, b, c, n + 2);for (int i = 0; i <= n; i++)res[i] = c[n - i + 1]; } int main() {int n; read(n);init(n + 1);getans(n, odd);getans(n - 1, even);for (int i = n; i >= 1; i--)update(even[i], 1ll * even[i - 1] * (n - i) % P);NTT :: times(odd, even, res, n + 1);for (int i = 1; i <= 2 * n - 1; i++)printf("%d ", res[i]);return 0; }總結(jié)
以上是生活随笔為你收集整理的【省内训练2018-11-23】Bishop的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: wps excel 怎么复制工作表?(移
- 下一篇: 微型计算机能不能玩lol,微机课才能玩的