[PA2019] Desant Solution
[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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下