QAQ我把高精写挂辽
开始考虑的是f[i][j]表示消掉区间i~j然后我没搞好 现在再打好像又知道了 (?????)
按照最最最初的想法f[i][j]表示还剩区间i~j 然后就从大区间转到小区间
#include<bits/stdc++.h> using namespace std; #define Max(x,y) (x)<(y)?(y):(x) #define Min(x,y) (x)<(y)?(x):(y) #define ll long long #define rg register #define lson o<<1 #define rson o<<1|1 const int N=100+5,M=1000000+5,inf=0x3f3f3f3f,P=19650827; const int power=4,base=10000; int n,m,a[N]; template <class t>void rd(t &x){ x=0;int w=0;char ch=0; while(!isdigit(ch)) w|=ch=='-',ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); x=w?-x:x; } struct num{ int a[N]; num(){memset(a,0,sizeof(a));} num(int x){//低精度转高精度 memset(a,0,sizeof(a)); int t=0; while(x) a[++t]=x%base,x/=base; a[0]=t; } void print(){ printf("%d",a[a[0]]); for(rg int i=a[0]-1;i>0;--i) printf("%0*d",power,a[i]); puts(""); } }bas[N],ans,f[N][N]; num operator *(const num &p,const int &q) { num c; c.a[0]=p.a[0]; for(int i=1;i<=p.a[0];++i) c.a[i]=p.a[i]*q; for(rg int i=1;i<=c.a[0]+1;++i) if(c.a[i]>=base) c.a[i+1]+=c.a[i]/base,c.a[i]%=base; if(c.a[c.a[0]+1]) ++c.a[0]; return c; } bool operator <(const num &p,const num &q) { if(p.a[0]<q.a[0]) return 1; if(p.a[0]>q.a[0]) return 0; for(rg int i=p.a[0];i>0;--i) if(p.a[i]!=q.a[i]) return p.a[i]<q.a[i]; return 0; } num operator +(const num &p,const num &q) { num c; c.a[0]=max(p.a[0],q.a[0]); for(int i=1;i<=c.a[0];++i) c.a[i]+=p.a[i]+q.a[i]; for(int i=1;i<=c.a[0]+1;++i) if(c.a[i]>=base) c.a[i+1]+=c.a[i]/base,c.a[i]%=base; if(c.a[c.a[0]+1]) ++c.a[0]; return c; } void pre(){ bas[0]=num(1),ans=num(0); for(int i=1;i<=m;++i) bas[i]=bas[i-1]*2; } int main(){ freopen("in.txt","r",stdin); rd(n),rd(m); pre(); for(int h=1;h<=n;++h){ num mx=num(0); for(int i=1;i<=m;++i) rd(a[i]); for(int i=1;i<=m;++i) for(int j=1;j<=m;++j) f[i][j]=num(0); for(int i=1;i<=m;++i) for(int j=m;j>=i;--j) f[i][j]=Max(f[i][j],Max(f[i-1][j]+bas[m-j+i-1]*a[i-1],f[i][j+1]+bas[m-j+i-1]*a[j+1])); for(int i=1;i<=m;++i) mx=Max(mx,f[i][i]+bas[m]*a[i]); ans=ans+mx; } ans.print(); return 0; }