1. 程式人生 > >山東省第九屆省賽G題game

山東省第九屆省賽G題game

num -- 狀態 山東省 spa ems memset 只需要 con

題目是一個很像NIM博弈的一道dp問題,實際上就是利用了NIM博弈的結論,XOR為0

原題目的意思是給定n堆石頭,可以取走0-d堆石頭,問取走之後後手必勝(實際上就是xor為0的情況)的取法數目

就是利用dp,狀態表示就是前i堆,取走j堆,xor值為k

初始化的的狀態就是dp[i,0,0]=1;

轉移方程為dp[i,j,k]=dp[i-1,j,k]+dp[i-1,j-1,k^val[i]];

也就是由第i堆不取產生k的情況,和第i堆取走之後前i-1堆k^val[i]的值

計算所有堆的抑或值,這樣取出來的堆只需要值為sum就相當於取走直接剩下的抑或值為0

最後只需要計算dp[n][i][sum]的值,i∈[0,d],其中i=0的情況等價於sum=0的情況,直接處理

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 
 5 const int MOD=(int)1e9+7;
 6 
 7 int dp[1001][12][1030];
 8 int num[1005];
 9 
10 int main(){
11     int T;
12     std::cin>>T;
13     while(T--)
14     {
15         memset(dp,0,sizeof(dp));
16 int n,d; 17 scanf("%d%d",&n,&d); 18 int sum=0; 19 for(int i=1;i<=n;i++) 20 { 21 scanf("%d",&num[i]); 22 sum^=num[i]; 23 } 24 25 for(int i=0;i<=n;i++) 26 { 27 dp[i][0][0]=1;
28 } 29 30 for(int i=1;i<=n;i++) 31 { 32 for(int j=1;j<=d;j++) 33 { 34 for(int k=0;k<=1023;k++) 35 { 36 dp[i][j][k]=(dp[i-1][j][k]+dp[i-1][j-1][k^num[i]])%MOD; 37 } 38 } 39 } 40 41 int ans=0; 42 for(int i=1;i<=d;i++) 43 { 44 ans=(ans+dp[n][i][sum])%MOD; 45 } 46 if(sum==0) ans++; 47 48 printf("%d\n",ans); 49 50 } 51 return 0; 52 }

山東省第九屆省賽G題game