题目链接
题目思路
这个题目我能想到的\(dp\)是两个常规的
\(dp[i]\)表示以\(i\)结尾然后\(O(n^2)\)转移
\(dp[i][j]\)表示以二元组\((i,j)\)结尾的答案然后以\(O(250^2\times n)\)转移
显然都不行...
正解真的有点阴间
设\(dp[i][j]\)表示现在的\(a=j\)上一个\(a=i\)
然后进行转移
感觉说也说不明白到底是啥...相当于分开考虑两边的贡献
确实挺对的...
代码
#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
int n,A,B;
int a[maxn],b[maxn];
ll ans[maxn];
ll dp[505][505];
int f(int x){
return A*(x%100)*(x%100)+B*x;
}
signed main(){
scanf("%d%d%d",&n,&A,&B);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
scanf("%d",&b[i]);
}
for(int i=1;i<=500;i++){
for(int j=1;j<=500;j++){
dp[i][j]=-1e18;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=500;j++){
ans[i]=max(ans[i],dp[j][a[i]]+f(j*b[i]));
}
for(int j=1;j<=500;j++){
dp[a[i]][j]=max(dp[a[i]][j],ans[i]-f(b[i]*j));
}
}
ll pr=0;
for(int i=1;i<=n;i++){
pr=max(pr,ans[i]);
}
printf("%lld\n",pr);
return 0;
}