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;
}