题解——P1108低价购买(DP)
第一问是最长下降子序列,n很小,n^2可过,注意最长下降子序列的枚举顺序即可
for(int i=1;i<=n;i++)//不要写错 for(int j=1;j<i;j++)//不要打成<= if(a[i]<a[j]&&b[i]<b[j]+1) b[i]=b[j]+1;
第二问统计方案数
我们设cnt[i]表示以i结尾的最长下降子序列的长度
然后转移方案数
如果a[i]<a[j]&&b[i]==b[j]+1
就可以把原序列拼接上去
如果相等,则前面已经包含此情况,b[j]=0
over
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; int a[5050],b[5050],c[5050],n,ans=1,cnt[5050],ansc=0; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=1,c[i]=i; for(int i=1;i<=n;i++){ for(int j=1;j<i;j++) if(a[i]<a[j]&&b[j]+1>b[i]){ b[i]=b[j]+1; c[i]=j; ans=max(ans,b[i]); } if(!b[i]) b[i]=1; } // for(int i=1;i<=n;i++) // printf("i=%d a=%d b=%d\n",i,a[i],b[i]); for(int i=1;i<=n;i++){ for(int j=1;j<i;j++){ if(a[i]<a[j]&&b[i]==b[j]+1) cnt[i]+=cnt[j]; else if(a[j]==a[i]&&b[j]==b[i]){ cnt[j]=0; } } if(!cnt[i]) cnt[i]=1; } for(int i=1;i<=n;i++) if(b[i]==ans){ ansc+=cnt[i]; } printf("%d %d\n",ans,ansc); return 0; }