[SDOI 2011]黑白棋
阿新 • • 發佈:2018-03-25
print mar pro 移動 clu 顏色不同 time markdown ble
Description
題庫鏈接
給出一個 \(1\times n\) 的棋盤,棋盤上有 \(k\) 個棋子,一半是黑色,一半是白色。最左邊是白色棋子,最右邊是黑色棋子,相鄰的棋子顏色不同。
小 \(A\) 可以移動白色棋子,小 \(B\) 可以移動黑色的棋子,他們每次操作可以移動 \(1\sim d\) 個棋子。
每當移動某一個棋子時,這個棋子不能跨越兩邊的棋子,當然也不可以出界。當誰不可以操作時,誰就失敗了。
小 \(A\) 和小 \(B\) 輪流操作,現在小 \(A\) 先移動,問有多少種初始棋子的布局使他勝利。
\(1\leq n\leq 10000,1\leq k\leq 100\)
Solution
是一道假題...參考了 黃學長的做法 ... 具體可以參見他的博客。
Code
#include <bits/stdc++.h>
using namespace std;
const int yzh = 1000000007, N = 10000;
int n, k, d, a[N+5], b[N+5], bin[20], f[16][N+5];
int C(int n, int m) {return 1ll*a[n]*b[m]%yzh*b[n-m]%yzh; }
void work() {
scanf("%d%d%d", &n, &k, &d);
a[0 ] = b[0] = a[1] = b[1] = bin[0] = 1;
for (int i = 2; i <= n; i++) b[i] = -1ll*yzh/i*b[yzh%i]%yzh;
for (int i = 2; i <= n; i++) a[i] = 1ll*i*a[i-1]%yzh, b[i] = 1ll*b[i]*b[i-1]%yzh;
for (int i = 1; i < 20; i++) bin[i] = (bin[i-1]<<1);
f[0][0] = 1;
for (int i = 0; i < 15; i++)
for (int j = 0; j <= n-k; j++)
for (int p = 0; p*(d+1) <= k/2 && p*(d+1)*bin[i]+j <= n-k; p++)
(f[i+1][p*(d+1)*bin[i]+j] += 1ll*f[i][j]*C(k/2, p*(d+1))%yzh) %= yzh;
int ans = C(n, k);
for (int i = 0; i <= n-k; i++)
(ans -= 1ll*f[15][i]*C(n-k/2-i, k/2)%yzh) %= yzh;
printf("%d\n", (ans+yzh)%yzh);
}
int main() {work(); return 0; }
[SDOI 2011]黑白棋