秘密构成 题解(神仙dp)

题目链接

题目思路

这个题目我能想到的\(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;
}

不摆烂了,写题
原文地址:https://www.cnblogs.com/hunxuewangzi/p/15485347.html