区间DP+__int128高精

每次看到高精的题总是想着可以跳过,或者可以直接用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;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值