低价购买(cogs2724)
这个题主要分为两个部分,一个是求严格的最长下降子序列,还有就是求方案数,第一个问题超简单,不用说,第二个算法有些困难,所以在此贴代码
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=5010; int n,a[maxn],f[maxn],b[maxn]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); f[i]=1; } int ans=1,tot=0; for(int i=2;i<=n;i++) { for(int j=1;j<i;j++) if(a[j]>a[i]) f[i]=max(f[i],f[j]+1); ans=max(ans,f[i]); } for(int i=1;i<=n;i++) { if(f[i]==1) b[i]=1;//这个很重要,说明只有一个数的时候就应该方案数为1 for(int j=1;j<i;j++) { if((f[i]==f[j]+1)&&a[j]>a[i]) b[i]+=b[j]; if(f[i]==f[j]&&a[j]==a[i]) f[j]=0;//如果两个数相等,并且序列长度也相等的时候,使前面的消失 } } for(int i=1;i<=n;i++) if(f[i]==ans) tot+=b[i];//这个语句不能写在上面,因为你在上面有时会重置fi,所以必须重新循环 printf("%d %d",ans,tot); } /** 12 68 69 54 64 68 64 70 67 78 62 98 87 5 62 62 68 85 100 **/