题意:给定四个数组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;
}