本蒟蒻在dp时,如果发现结果大于1e18,就返回1e18+10。因为如果最终的最小代价大于1e18,不会影响输出;如果最终的最小代价小于1e18,那最终的答案肯定不会从这转移,那这赋一个大点的值就好。可是WA了,30pts。有没有大佬解答QAQ
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void rd(int &p){
p=0;char c=getchar();ll f=1;
while(c>'9'||c<'0'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9')p=(p<<1)+(p<<3)+c-'0',c=getchar();
p*=f;
}
void rdl(ll &p){
p=0;char c=getchar();ll f=1;
while(c>'9'||c<'0'){if(c=='-')f=-f;c=getchar();}
while(c>='0'&&c<='9')p=(p<<1)+(p<<3)+c-'0',c=getchar();
p*=f;
}
const int N=1e5+50;
ll inf=1000000000000000010ll;
int t,n,L,k,p[N],tp,tl;
char c[N][35];
ll qp(ll x,int y){
ll an(1);
if(!x&&y)return 0ll;
for(;y;y>>=1){
if(y&1){
if(an>(inf-10ll)/x)return inf;
an*=x;
}
if(x>(inf-10ll)/x)x=inf;
else x=x*x;
}
return an;
}
ll f[N],s[N];
struct sol{
int l,r,pr;
}b[N];
ll val(int i,int j){
f[n+1]=qp(1ll*abs(s[i]-s[j]-L+i-j-1),k);
if(f[j]>(inf-10ll)-f[n+1])return inf;
return f[j]+f[n+1];
}
int main(){
rd(t);
while(t--){
rd(n),rd(L),rd(k);
for(int i(1);i<=n;++i)scanf("%s",c[i]+1);
for(int i(1);i<=n;++i){
s[i]=1ll*strlen(c[i]+1)+s[i-1];
}tp=tl=1;b[tp]=sol{1,n,0};
for(int i(1),u,v,mid;i<=n;++i){
p[i]=b[tl].pr;
if(b[tl].l==b[tl].r)++tl;
else ++b[tl].l;
f[i]=val(i,p[i]);
while(tl<=tp&&val(b[tp].l,b[tp].pr)>=val(b[tp].l,i))--tp;
if(tl>tp){
b[++tp]=sol{i+1,n,i};continue;
}
if(val(b[tp].r,b[tp].pr)<val(b[tp].r,i))u=b[tp].r+1;
else{
u=b[tp].l,v=b[tp].r;
while(u<v){
mid=u+v>>1;
if(val(mid,b[tp].pr)>val(mid,i))v=mid;
else u=mid+1;
}
b[tp].r=u-1;
}
if(u<=n)b[++tp]=sol{u,n,i};
}
if(f[n]>inf-10ll)printf("Too hard to arrange\n");
else{
printf("%lld\n",f[n]);
k=n;
while(k){
s[k]=-1;k=p[k];
}
for(int i(1);i<=n;++i){
printf("%s",c[i]+1);
if(s[i]==-1ll)printf("\n");
else printf(" ");
}
}
printf("--------------------");
if(t)printf("\n");
}
return 0;
}