山東省第九屆省賽G題game
阿新 • • 發佈:2019-04-06
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