【BZOJ2281】【博弈论+DP】 [Sdoi2011]黑白棋
生活随笔
收集整理的這篇文章主要介紹了
【BZOJ2281】【博弈论+DP】 [Sdoi2011]黑白棋
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Description
黑白棋(game) 【問題描述】 小A和小B又想到了一個新的游戲。 這個游戲是在一個1*n的棋盤上進行的,棋盤上有k個棋子,一半是黑色,一半是白色。 最左邊是白色棋子,最右邊是黑色棋子,相鄰的棋子顏色不同。 E 小A可以移動白色棋子,小B可以移動黑色的棋子,他們每次操作可以移動1到d個棋子。 每當移動某一個棋子時,這個棋子不能跨越兩邊的棋子,當然也不可以出界。當誰不可以操作時,誰就失敗了。 小A和小B輪流操作,現在小A先移動,有多少種初始棋子的布局會使他勝利呢?Input
共一行,三個數,n,k,d。Output
輸出小A勝利的方案總數。答案對1000000007取模。Sample Input
10 4 2Sample Output
182【數據規模和約定】
對于100%的數據,有1<=d<=k<=n<=10000, k為偶數,k<=100。
HINT
Source
stage 2 day1
【分析】
很經典的題目,很不錯。
我們將相鄰的棋子看成一對,顯然,在最后的情況下,每對棋子都是緊貼在一起的。
對于每對棋子,白棋在左邊,黑棋在右邊,那么白棋就只能往右邊走,黑棋也只能往左邊走,否則若白棋往左邊,黑棋也可以往左邊,情況不會有改變。
那么若將每對棋子之間的距離看成一堆石子的數量,就變成經典的nim游戲。
然后用nimk的理論做就行了。
DP有點難想...看代碼就看得懂了
1 /* 2 唐代白居易 3 《問劉十九》 4 綠蟻新醅酒,紅泥小火爐。 5 晚來天欲雪,能飲一杯無。*/ 6 7 #include <set> 8 #include <map> 9 #include <cmath> 10 #include <cstdio> 11 #include <vector> 12 #include <cstring> 13 #include <cstdlib> 14 #include <iostream> 15 #include <algorithm> 16 #define LOCAL 17 const int MAXL = 20; 18 const long long MOD = 1000000007; 19 const int MAXK = 10000 + 10; 20 const int MAXN = 10000 + 10; 21 using namespace std; 22 typedef long long ll; 23 ll f[100][MAXN * 2]; 24 ll c[MAXK][1000], n, K, d; 25 26 ll C(ll a, ll b){ 27 if (a == b) return 1ll; 28 //if (b > a - b) b = a - b; 29 return c[a][b] % MOD; 30 } 31 void prepare(){//預處理組合數 32 memset(c, 0, sizeof(c)); 33 c[0][0] = 1; 34 for (ll i = 1; i <= 10005ll; i++){ 35 c[i][0] = 1ll; 36 //if (i <= 210) c[i][i] = 1; 37 for (ll j = 1; j < min(i, 250ll); j++) 38 c[i][j] = (C(i - 1, j) + C(i - 1, j - 1)) % MOD; 39 } 40 //for (ll i = 1; i <= 50; i++) 41 //for (ll j = 0; j <= i; j++) printf("%d %d:%d\n", i, j, C[i][j]); 42 //printf("%d\n", C[10][2]); 43 } 44 void dp(){ 45 K /= 2; 46 memset(f, 0, sizeof(f)); 47 f[0][0] = 1;//第0位 48 for (ll i = 1; i <= 15; i++){ 49 for (ll j = 0; j <= n - 2 * K; j++)//注意這一層不需要枚舉到n了,因為只有這么多的空位 50 for (ll k = 0; (k * (d + 1) <= K) && (k * (d + 1) * (1ll<<(i - 1)) <= j); k++){ 51 f[i][j] = (f[i][j] + (f[i - 1][j - k * (d + 1) * (1ll<<(i - 1))] * C(K, k * (d + 1))) % MOD) % MOD; 52 53 } 54 } 55 ll Ans = 0; 56 for (ll i = 0; i <= n - 2 * K; i++) Ans = (Ans + (f[15][i] * C(n - i - K * 2 + K, K)) % MOD) % MOD; 57 printf("%lld\n", (C(n, 2 * K) - Ans + MOD) % MOD); 58 } 59 60 int main(){ 61 62 prepare(); 63 scanf("%lld%lld%lld", &n, &K, &d); 64 dp(); 65 //n的距離,k個石頭,1~d次移動 66 return 0; 67 } View Code?
轉載于:https://www.cnblogs.com/hoskey/p/4357482.html
總結
以上是生活随笔為你收集整理的【BZOJ2281】【博弈论+DP】 [Sdoi2011]黑白棋的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS中assign、copy 、ret
- 下一篇: linux ubuntu 安装jdk