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]);

浙公网安备 33010602011771号