1 条题解
-
0
这题要求最长下降子序列的长度和个数,我们可以增加 数组maxlen[size](记录当前第1个点到第i个点之间的最长下降序列长度) 和maxnum[size](记录1~i之间的最长下降序列个数 ) ,首先对于最长下降序列属于DP基础题,只要对每一个a[i]求出符合要求(a[i] < a[j])的max( maxlen[j] + 1)即可,主要难点在第二步求下降序列总数
在序列中,如果maxlen[j]+1 == maxlen[i]则说明a[i]和a[j]在同一个下降数列中(显然必有a[i]<a[j]),那么我们只要将每一种符合要求的状态maxnum[j]转移到maxnum[i]中就可以了,有几个细节需要注意,题目要求序列是严格递减的,那么对于两个相同的数我们只能记录一个合法解,那么程序必须只记录两个相同数之间的状态,在这里用倒推可以简化编程,只要找到一个等于的就直接跳出循环,还要注意,如果从当前的a[i]一直找到相等的a[j]在这之间都没有可行状态的话,当maxnum[i]默认值为1要修改为0(避免错误计算),为0的当然无需处理。 ———————————————— 版权声明:本文为CSDN博主「zhang360896270」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/zhang360896270/article/details/6701589
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int a[5010],f[5010]; struct int128 { int f[100],tot; void clear()//清零 { for(int i=0;i<=99;i++) f[i]=0; tot=0; } void out()//输出 { for(int i=tot;i>=1;i--) printf("%d",f[i]); printf("\n"); } int128 operator + (const int128 &a)const//重载高精加 { int128 c; c.clear(); c.tot=a.tot>tot?a.tot:tot; int x=0; for(int i=1;i<=c.tot;i++) { c.f[i]=a.f[i]+f[i]+x; x=c.f[i]/10; c.f[i]%=10; } if(x)c.f[++c.tot]=1; return c; } }; int128 s[5010],num; int main() { int n,ans=0; scanf("%d",&n); for(int i=1; i<=n; i++) scanf("%d",&a[i]); for(int i=1; i<=n; i++) { int t=0; for(int j=i-1; j>=1; j--)//最长下降子序列 if(a[i]<a[j]&&f[j]>t) t=f[j]; f[i]=t+1; if(f[i]==1) s[i].tot=s[i].f[1]=1; for(int j=i-1;j>=1;j--) { if(a[i]<a[j]&&f[j]==t)//统计s[i] s[i]=s[i]+s[j]; else if(a[i]==a[j]&&f[i]==f[j])//如果a[i]==a[j]&&f[i]==f[j],将s[j]清零 s[j].clear(); } ans=ans>t+1?ans:t+1; } for(int i=1; i<=n; i++) if(f[i]==ans) num=num+s[i];//统计答案 printf("%d ",ans); num.out(); return 0; }
- 1
信息
- ID
- 953
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者