2/8 P1005 高精度+区间DP

https://www.luogu.com.cn/problem/P1005

AC代码
#include <bits/stdc++.h>
using namespace std;
#define LL long long int
#define N 85
const int MOD=10000,MAX=85;
int n,m,maps[MAX];
struct HP{
	int p[505],len;
	HP(){
		memset(p,0,sizeof(p));
		len=0;
	} 
	void print(){
		cout<<p[len];
		for(int i=len-1;i>=1;i--){
			if(p[i]==0)
			{
				cout<<"0000";
				continue;
			}
			for(int k=10;k*p[i]<MOD;k*=10){
				cout<<"0";
			}
			cout<<p[i];
		}
	} 
}dp[MAX][MAX],base[MAX],ans;

HP operator +(const HP &a,const HP &b){
	HP c;
	c.len=max(a.len,b.len);
	int x=0;
	for(int i=1;i<=c.len;i++)
	{
		c.p[i]=a.p[i]+b.p[i]+x;
		x=c.p[i]/MOD;
		c.p[i]%=MOD;
	}
	if(x>0) c.p[++c.len]=x;
	return c;
} 

HP operator *(const HP &a,const int &b){
	HP c;
	c.len=a.len;
	int x=0;
	for(int i=1;i<=c.len;i++)
	{
		c.p[i]=a.p[i]*b+x;
		x=c.p[i]/MOD;
		c.p[i]%=MOD;
	}
	while(x>0){
		c.p[++c.len]=x%MOD;
		x/=MOD;
	}
	return c;
}

HP max(const HP &a,const HP &b){
	if(a.len>b.len) return a;
	else if(b.len>a.len) return b;
	for(int i=a.len;i>=1;i--)
	{
		if(a.p[i]>b.p[i]) return a;
		else if(a.p[i]<b.p[i]) return b;
	}
	return a;
}

void base_init(){
	base[0].p[1]=1;
	base[0].len=1;
	for(int i=1;i<=m+2;i++){
		base[i]=base[i-1]*2;
	}
}

int main()
{
	cin>>n>>m;
	base_init();
	for(int i=1;i<=n;i++)
	{
		memset(dp,0,sizeof(dp));
		for(int j=1;j<=m;j++)
		{
			cin>>maps[j];
		}
		for(int j=1;j<=m;j++)
		{
			for(int k=m;k>=j;k--)
			{
				dp[j][k]=max(dp[j][k],dp[j][k+1]+base[m-k+j-1]*maps[k+1]);
				dp[j][k]=max(dp[j][k],dp[j-1][k]+base[m-k+j-1]*maps[j-1]);
			}
		}
		HP M;
		for(int j=1;j<=m;j++)
		{
			M=max(M,dp[j][j]+base[m]*maps[j]);
		}
		ans=ans+M;
	}
	ans.print();
	return 0;
}

高精+高精:
HP operator +(const HP &a,const HP &b){
	HP c;
	c.len=max(a.len,b.len);
	int x=0;
	for(int i=1;i<=c.len;i++)
	{
		c.p[i]=a.p[i]+b.p[i]+x;
		x=c.p[i]/MOD;
		c.p[i]%=MOD;
	}
	if(x>0) c.p[++c.len]=x;
	return c;
}
高精*单精:
HP operator *(const HP &a,const int &b){
	HP c;
	c.len=a.len;
	int x=0;
	for(int i=1;i<=c.len;i++)
	{
		c.p[i]=a.p[i]*b+x;
		x=c.p[i]/MOD;
		c.p[i]%=MOD;
	}
	while(x>0){
		c.p[++c.len]=x%MOD;
		x/=MOD;
	}
	return c;
}
高精*高精
HP operator*(const HP &a, const HP &b) {
    HP c;
    c.len = a.len + b.len; // 初始化结果的长度为两个高精度数长度之和
    memset(c.p, 0, sizeof(c.p)); // 将结果数组初始化为0

    // 两重循环计算每一位的乘积
    for (int i = 1; i <= a.len; i++) {
        for (int j = 1; j <= b.len; j++) {
            c.p[i + j - 1] += a.p[i] * b.p[j]; // 计算每一位的乘积并累加到对应位置
        }
    }

    // 处理进位
    for (int i = 1; i <= c.len; i++) {
        if (c.p[i] >= MOD) { // 如果当前位的值大于等于MOD,需要进位
            c.p[i + 1] += c.p[i] / MOD; // 计算进位值
            c.p[i] %= MOD; // 当前位的值取余数
        }
    }

    // 如果最高位有进位,更新结果的长度
    if (c.p[c.len + 1] > 0) {
        c.len++;
    }

    return c;
}
高精比较
HP max(const HP &a,const HP &b){
	if(a.len>b.len) return a;
	else if(b.len>a.len) return b;
	for(int i=a.len;i>=1;i--)
	{
		if(a.p[i]>b.p[i]) return a;
		else if(a.p[i]<b.p[i]) return b;
	}
	return a;
}

DP思路:
设区间为J(i,j)
每次取数都是maps[i-1]或者maps[j+1],从这两个状态转移:

dp[j][k] = max (dp[j][k] , dp[j][k+1] + base[m-k+j-1] * maps[k+1])
dp[j][k] = max (dp[j][k] , dp[j-1][k] + base[m-k+j-1] * maps[j-1])

由于最终会停在长度为一的区间,不会取完,最后需要手动再dp一次:

M = max (M , dp[j][j] + base[m] * maps[j]);

posted @ 2025-02-08 14:07  石磨豆浆  阅读(7)  评论(0)    收藏  举报