P1005 矩阵取数游戏 DP+__int128

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; 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章