【2018ACM山东省赛 - G】Games(Nim博弈 + dp)
題干:
Problem Description
Alice and Bob are playing a stone game. There are nnn piles of stones. In each turn, a player can remove some stones from a pile (the number must be positive and not greater than the number of remaining stones in the pile). One player wins if he or she remove the last stone and all piles are empty. Alice plays first.
To make this game even more interesting, they add a new rule: Bob can choose some piles and remove entire of them before the game starts. The number of removed piles is a nonnegative integer, and not greater than a given number ddd. Note ddd can be greater than nnn, and in that case you can remove all of the piles.
Let ansansans denote the different ways of removing piles such that Bob are able to win the game if both of the players play optimally. Bob wants you to calculate the remainder of ansansans divided by 109+710^9+7109+7.
Input
The first line contains an integer TTT, representing the number of test cases.
For each test cases, the first line are two integers nnn and ddd, which are described above.
The second line are nnn positive integers aia_iai?, representing the number of stones in each pile.
T≤5,n≤103,d≤10,ai≤103T \leq 5, n \leq 10^3, d \leq 10, a_i \leq 10^3T≤5,n≤103,d≤10,ai?≤103
Output
For each test case, output one integer (modulo 109+710^9 + 7109+7) in a single line, representing the number of different ways of removing piles that Bob can ensure his victory.
Sample Input
2 5 2 1 1 2 3 4 6 3 1 2 4 7 1 2Sample Output
2 5題目大意:
? 剝去博弈的外皮,簡化之后的題意是:給定n個數,一個x,讓你最多可以選擇d個數,求異或和為x的方案數。
解題報告:
? 直接dp就行了,用滾動數組空間優化掉一維。(方法和01背包一樣倒著遍歷)
AC代碼:
//C #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<cctype> using namespace std; typedef long long ll; const int MAX=1<<11; const int mod=1e9+7; //a=num[1]^num[2]^..^num[n]; //選i(0<=i<=d)個數使異或和等于a //dp[i][d][v]從前i個數中選d個數, 異或和為v的方案數 //dp[i][d][v]=dp[i-1][d][v]+dp[i-1][d-1][v^val[i]]; int n,d,val[MAX+5]; ll dp[15][MAX+5]; //滾動減掉第一維 int main() {int t,q,i,j,k,sum;ll ans=0;cin>>t;for(;t;t--){scanf("%d%d",&n,&d); d=min(d,n);ans=sum=0;for(i=1;i<=n;i++){scanf("%d",&val[i]);sum^=val[i];}//initfor(i=0;i<=d;i++){for(j=0;j<=MAX;j++)dp[i][j]=0;}dp[0][0]=1;for(i=1;i<=n;i++){for(j=d;j>=1;j--){for(k=0;k<=MAX;k++){dp[j][k]=(dp[j][k]+dp[j-1][k^val[i]])%mod;}} }for(i=0;i<=d;i++)ans=(ans+dp[i][sum])%mod;printf("%lld\n",ans);}return 0; }?
總結
以上是生活随笔為你收集整理的【2018ACM山东省赛 - G】Games(Nim博弈 + dp)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 美元要失去主导货币地位?如果真有那么一天
- 下一篇: spmgr.exe - spmgr是什么