[PA2019] Desant Solution
dengchengyu · · 题解
[PA2019] Desant Solution
推销。
原题链接。
题目大意:给定一个长为
解题思路:首先有一个暴力的做法,设
对于考虑完了前
考虑计算状态的个数,我们就是求和为 但是根据小学奥数,我们只要尽可能多拆
再回到状态上来,我们可以对于第 vector 连续开
而对于转移,每次决策选或不选都会合并两个区间。暴力地拆出状态的每一位和合并状态的每一位即可。
时间复杂度 long long。
AC 代码:
int n;
const int N=45;
int a[N];
int l[N],w[N][N],c[N][N];
vector<pair<int,ll> > f[N];
int now[N];
void getmax(pair<int,ll> &x,pair<int,ll> y){
if(x.first>y.first)x=y;
else if(x.first==y.first)x.second+=y.second;
}
signed main(){
read(n);
fo(i,1,n){
read(a[i]);
}
fo(i,0,n){
fo(j,i+1,n){
c[i][++l[i]]=a[j];
}
c[i][++l[i]]=n+1;
sort(c[i]+1,c[i]+1+l[i]);
int t=1;
fo(j,1,l[i]){
w[i][j]=t;
t*=c[i][j]-c[i][j-1];
}
f[i]=vector<pair<int,ll>>(t,{1e9,0});
}
f[0][0]={0,1};
fo(i,0,n-1){
int at=0;
fo(j,1,l[i])if(c[i][j]==a[i+1])at=j;
fu(j,0,f[i].size()){
int t=j;
fd(k,l[i],1){
now[k]=t/w[i][k];
t%=w[i][k];
}
int cnt=0;
fo(k,at+1,l[i])cnt+=now[k];
int t1=0,t2=0;
fo(k,1,at-1)t1+=now[k]*w[i+1][k];
fo(k,at+2,l[i])t1+=now[k]*w[i+1][k-1];
t2=t1;
t1+=(now[at]+now[at+1])*w[i+1][at];
t2+=(now[at]+now[at+1]+1)*w[i+1][at];
getmax(f[i+1][t1],f[i][j]);
getmax(f[i+1][t2],{f[i][j].first+cnt,f[i][j].second});
}
}
fo(i,1,n)write(f[n][i].first,' ',f[n][i].second,'\n');
return 0;
}