P10236 题解
P10236题解
前言:
黑润心有错夏令营讲了这道题,我本想抄题解的,结果发现看不懂前几篇,只能自己写一篇啦。
正文:
算法判断:
我们可以发现这个操作只能删去头和尾,所以无论经过多少次合法的操作,得到的数组一定是原串的子串。什么?连续?好!区间动态规划,启动!
状态定义:
我们定义
如何转移:
我们知道
计算得分:
举个栗子:
推出方程
我们现在就可以推出方程了:
得到答案
根据题意我们的答案是
补充
我们现在把代码交了上去交了,啊?为什么不对?
对了!记得要用快速幂,还一定要特判
code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll mod=998244353;
ll quickpow(ll x,ll y)
{
if(x==0&&y==0)
{
return 0;//特判!!!
}
ll ans=1,p=x;
while(y>0)
{
if(y&1)
{
ans=(ans*p)%mod;
}
p=(p*p)%mod;
y>>=1;
}
return ans;
}
ll T,dp[1009][1009][2],a[1009],n;
int main()
{
cin>>T;
while(T--)
{
cin>>n;
for(ll i=1;i<=n;i++)
{
cin>>a[i];
}
memset(dp,0,sizeof(0));//多测清空
for(ll len=n;len>=1;len--)//按题目顺序枚举长度
{
for(ll i=1;i<=n-len+1;i++)//枚举左右端点
{
ll j=i+len-1;
dp[i][j][0]=max(dp[i-1][j][0]+quickpow(a[i-1],a[i]),dp[i][j+1][1]+quickpow(a[j+1],a[i]));
dp[i][j][1]=max(dp[i-1][j][0]+quickpow(a[i-1],a[j]),dp[i][j+1][1]+quickpow(a[j+1],a[j]));
}
}
ll ans=0;
for(ll i=1;i<=n;i++)//统计答案
{
ans=max(ans,dp[i][i][0]);
ans=max(ans,dp[i][i][1]);
}
cout<<ans<<endl;
}
return 0;
}