每次看到高精的题总是想着可以跳过,或者可以直接用python自带的高精直接写出来,这次在ljz的强压下,咬着牙把int128看了一遍,其实就是懒。whatever,既然看了就记点笔记吧。
这是一个明显的区间DP问题,状态转移方程也比较好推,令DP[i][j]表示第i位置到第j位置之间可以取得的数的最大值(注意这里是指一行一行地来取数,所以需要进行n次循环来求的最后的总值)。接着就是状态转移方程了
DP[i][j]=max(DP[i+1][j]*2+2*a[i],DP[i][j-1]*2+2*a[j]) 中间需要好好理解一下为什么是简单的每一次成了2,没有明显地指出哪一个数最后是第几次取,也就是最后需要乘上的2的指数是多少,其实可以这样想,在区间i~j之间,要么先取i,要么先取j,先取a[i]那么接下来就取i+1~j之间的最大值,或者先取a[j]那么接下来就是取的i~j-1之间的最大值。
另一种更好理解,DP[i][j]=max(DP[i+1][j]+2^(m-(j-i))*a[i],DP[i][j-1]+2^(m-(j-i)*a[j]),也可以。
其次__int128一般只是在Linux系统下面才可以使用,但是大部分的OJ后台是Linux的,所以掌握一下还是有必要的,代码很好理解,下面看一下模板吧:
#include <bits/stdc++.h>
using namespace std;
inline __int128 read(){
__int128 x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
inline void print(__int128 x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9)
print(x/10);
putchar(x%10+'0');
}
int main(void){
__int128 a = read();
__int128 b = read();
print(a + b);
cout<<endl;
return 0;
}
下面就附上代码吧:
#include<bits/stdc++.h>
using namespace std;
const int maxn=81;
int n,m;
__int128 mp[maxn][maxn];
__int128 dp[maxn][maxn];
__int128 ans=0;
inline void input(__int128 &s)
{
s=0;
char c=' ';
while(c>'9'||c<'0') c=getchar();
while(c>='0'&&c<='9')
{
s=s*10+c-'0';
c=getchar();
}
}
inline void output(__int128 x)
{
if(x>9)
output(x/10);
putchar(x%10+'0');
}
__int128 solve(__int128 a[])
{
memset(dp,0,sizeof(dp));
for(int len=0;len<=m;len++)
for(int i=1;i+len<=m;i++)
dp[i][i+len]=max(2*dp[i+1][i+len]+a[i]*2,2*dp[i][i+len-1]+2*a[i+len]);
return dp[1][m];
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
input( mp[i][j]) ;
for(int i=1;i<=n;i++)
ans+=solve(mp[i]);
output(ans);
// system("pause");
return 0;
}