题意:给定四个数组a ,b ,p ,k 。 有两种操作 第一种 a[x]=a[x]^b[x] 第二种 a[x]=a[p[x]] + r ; 求经过u次操作使
得a[x]*k[x] 最大,其中x属于[1,n]
做法:首先考虑异或的性质 异或两次 就会变成原来数组 ,对于每个状态来说考虑还剩下多少步数,如果是偶数步以当前状态结束,如果是奇数步数以异或后的步数结束
其次考虑第二个操作,对当前状态直接进行操作二(步数减一),或者对异或后的状态执行状态二(步数减二)。
code:
#include <iostream> #include <stdio.h> #include <algorithm> #include <string.h> #include <queue> using namespace std; typedef long long ll; ll a[55],b[55], p[55],k[55], ans=0; ll n,u,r; void check(ll t[55]) { ll now=0; for(int i=1;i<=n;++i) now+=t[i]*k[i]; ans=max(now,ans); } void dfs(ll h[55],int step) { if(step==0) { check(h); return; } ll t1[55],t2[55]; for(int i=1;i<=n;++i) { t1[i]=h[i]^b[i]; } if(step%2) check(t1); else check(h); for(int i=1;i<=n;++i) { t2[i]=h[p[i]]+r; } dfs(t2,step-1); for(int i=1;i<=n;++i) { t2[i]=t1[p[i]]+r; } if(step>1) dfs(t2,step-2); } int main() { scanf("%I64d%I64d%I64d",&n,&u,&r); for(int i=1;i<=n; ++i) scanf("%I64d",&a[i]); for(int i=1;i<=n; ++i) scanf("%I64d",&b[i]); for(int i=1;i<=n; ++i) scanf("%I64d",&k[i]); for(int i=1;i<=n; ++i) scanf("%I64d",&p[i]); ans=0; dfs(a,u); printf("%I64d\n",ans); return 0; }
