链接:https://www.luogu.org/problem/show?pid=1108
题意:求最长下降子序列及去重方案数

第一问求 LIS 不解释
第二问主要难度在于去重
可以用 <nobr> g[i] </nobr>表示以第i个数字结尾的LIS方案数
代码附讲解

for(int i=1;i<=n;i++)
    {
        if(f[i]==1) g[i]=1; //相当于初始化,长度为1的LIS方案数也就只有一种
        for(int j=1;j<i;j++)//遍历i之前的所有数字
        {
            if(a[i]<a[j]&&f[i]==f[j]+1) g[i]+=g[j];//这两个判断条件就表明f【i】可以由f【j】转移而来,所以方案数要累加到g【i】上
            if(a[i]==a[j]&&f[i]==f[j]) f[j]=0;//难点!!这两个判断条件的意思是:如果两个数相同且以它为结尾的LIS长度也相同,那么后面的一定比前面的更优(因为凡是能转移到前面一个f【j】的状态,一定也能转移到f【i】,同时产生了重复计数),所以要把前面的无效状态归零,只保留后面的这个数。
        }
    }
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int f[5001],g[5001];
int a[5001];
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++)
    {
        f[i]=1;
        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) g[i]=1;
        for(int j=1;j<i;j++)
        {
            if(a[i]<a[j]&&f[i]==f[j]+1) g[i]+=g[j];
            if(a[i]==a[j]&&f[i]==f[j]) f[j]=0;
        }
    }
    int tot=0;
    for(int i=1;i<=n;i++)
        if(f[i]==ans)
        tot+=g[i];
    printf("%d %d",ans,tot);    
    return 0;
}