2020 计蒜之道 预赛 第三场 石子游戏(简单)(暴力DP)
石子游戏(简单)
思路:
通过形式容易看出是一道DP。其中异或和的情况只有64种,所以我们可以开一维来记录当前异或和的状态。
在[l,r]利用dp[当前位置][异或和][是否选择当前]来进行状态转移。时间复杂度为O(qnm)。
比赛时这道题卡了好久,思路很清晰,但就是跑不出正确结果。后来发现原来忽略了f为-1的情况,初始化默认为0了。。
题解:
#include<bits/stdc++.h>
#define MAX 1005
#define MOD 4294967296
using namespace std;
typedef long long ll;
int a[MAX],v[MAX];
int x[2005];
int dp[MAX][66][2];
int f[2005][66];
int main()
{
int t,n,m,q,l,r,i,j,k;
scanf("%d%d%d",&n,&m,&q);
for(i=0;i<n;i++){
scanf("%d%d",&a[i],&v[i]);
}
for(i=1;i<=q;i++){
scanf("%d%d%d",&l,&r,&x[i]);
memset(dp,-1,sizeof(dp));
dp[l][0][0]=0;
dp[l][a[l]][1]=v[l];
for(j=l+1;j<=r;j++){
for(k=0;k<64;k++){
dp[j][k][0]=max(dp[j-1][k][0],dp[j-1][k][1]);
dp[j][k][1]=max(dp[j-1][k^a[j]][0],dp[j-1][k^a[j]][1]);
if(dp[j][k][1]>-1) dp[j][k][1]+=v[j]; //-1一定要处理
}
}
for(k=0;k<64;k++){
f[i][k]=max(dp[r][k][0],dp[r][k][1]);
}
}
// for(i=1;i<=q;i++){
// for(j=0;j<64;j++){
// printf("%d ",f[i][j]);
// }
// printf("\n");
// }
ll ans=0;
for(k=1;k<=q;k++){
ll sum=0;
for(j=0;j<=m-1;j++){
sum+=f[k][j]*(x[k]^j)%MOD;
sum%=MOD;
}
ans+=(k^sum)%MOD;
ans%=MOD;
}
printf("%lld\n",ans);
return 0;
}
博文系博主原创,转载请注明出处 o(* ̄▽ ̄*)ブ 更多博文源自https://www.cnblogs.com/yzm10