2020 計蒜之道 預賽 第三場 石子游戲(簡單)(暴力DP)
阿新 • • 發佈:2020-09-21
石子游戲(簡單)
思路:
通過形式容易看出是一道DP。其中異或和的情況只有64種,所以我們可以開一維來記錄當前異或和的狀態。
利用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]; } } 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; }