标签:ios ring 表示 memset printf ++ span 初始 mod
题目是一个很像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 }
标签:ios ring 表示 memset printf ++ span 初始 mod
原文地址:https://www.cnblogs.com/rign/p/10661066.html