P1005 矩阵取数游戏
链接在此https://www.luogu.org/problem/P1005
先考虑部分分60分
可以看到dp是可以稳稳地得到60分的。
而dp思路就是将每一行单独求dp
dp方程式为
dp[i][j]=max(dp[i-1][j]+a[i]*fpow(2,n-(j-i)+1),dp[i][j]);
dp[i][j]=max(dp[i][j+1]+a[j]*fpow(2,n-(j-i)+1),dp[i][j]);
其中fpow为快速幂(这里有坑点)。表示2的(n-i+j+1)次方
然后i表示从开头取取到了第i个
j表示从结尾取取到了第j个
i和j都是数组的序号而不是从左往右或从右往左的个数。
剩下的就是高精度。手懒用了int128
要注意的是print时注意特判0的情况
还有fpow中的变量类型也要是int128
#include<bits/stdc++.h>
#define REP(i,a,b) for(int i(a); i<=(b);++i)
#define MAXN 100010
#define ll long long
#define bll __int128
using namespace std;
void read(int &x){
x=0; char c=getchar(); int f=1;
for(;!isdigit(c);c=getchar()) if (c=='-') f=-f;
for(;isdigit(c);c=getchar()) x=x*10+c-'0'; x*=f;
}
bll fpow(bll a,bll b){
bll ans=1;
while (b>0){
if (b%2) ans*=a;
a=a*a; b=b/2;
}
return ans;
}
void print(bll x){
if(!x) return;
if(x) print(x/10);
putchar(x%10+'0');
}
int n,m,a[MAXN];
bll dp[100][100];
int main(){
bll ANS=0;
read(m); read(n);
REP(QQ,1,m){
memset(dp,0,sizeof(dp));
memset(a,0,sizeof(a));
for(int i(1);i<=n;++i) read(a[i]);
for(int i(n+1);i>=1;i--) dp[0][i]=dp[0][i+1]+a[i]*fpow(2,n-i+1);
REP(i,1,n)
for(int j=n+1; j>i;j--){
dp[i][j]=max(dp[i-1][j]+a[i]*fpow(2,n-(j-i)+1),dp[i][j]);
dp[i][j]=max(dp[i][j+1]+a[j]*fpow(2,n-(j-i)+1),dp[i][j]);
}
bll ans=0;
REP(i,0,n){
ans=max(ans,dp[i][i+1]);
}
ANS+=ans;
}
if(ANS)
print(ANS); else cout<<"0"<<endl;
}