Problem:

n 个数,去除任意 m 个数,问最终能形成多少种不同的序列,对答案取模 1e9 + 7 输出

Solution:

设 dp[i][j] = k 表示前k个数,去除 m 个有 k 种
dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1] (dp[i - 1][j]:表示不去除第i个数;dp[i - 1][j - 1]:表示去除第i个数)
重复现象:
对于1,2,3,4,3,2,1,5来说,去除两个数的话会出现 (1,2,,,3,2,1,5),(1,2,3,,,2,1,5)这两种情况,而这两种得到的序列都是重复的
因此,我们计算的时候需要避免这种情况。
出现重复的原因就是删除连续数中存在两个相同的数,而重复的数量就是当前数a的位置为indexNow,上一次a出现的位置为indexLast,
固定(indexLast,indexNow)区间的数字和相同的两个数其中一个(indexLast或者indexNow)一定会被删除,而剩余还需要删除的数,
即从indexLast-1之前的数里面找j - (indxNow - indexLast))个。
因此重复的时候状态转移方程是
dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1] - dp[indexLast - 1][j - (i - indexLast)]

#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
#define _for(i,s,t) for(int i=s;i<t;i++)
#define _rof(i,s,t) for(int i=s;i>t;i--)
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define per(i,s,t) for(int i=s;i>=t;i--)
#define Ri(x) scanf("%d",&x)
#define Rii(x,y) scanf("%d%d",&x,&y)
#define INF 0x3f3f3f3f
using namespace std;
template<class T>inline void read(T &res)
{
    char c;T flag=1;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}
typedef long long ll;
const int maxn = 1e5 + 10;
const int mod = 1e9 + 7;
ll dp[maxn][11];
int s[maxn];
int main(){
    IOS;
    int n,m,k;
    while(cin>>n>>m>>k){
        rep(i,1,n){
            cin>>s[i];
        }
        dp[0][0] = 1;
        rep(i,1,n){// 第几个数
            dp[i][0] = 1; 
            rep(j,1,m){// 去除几个 
                dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1];
                dp[i][j] %= mod;
                if(i - j > 0)
                for(int k = i - 1;k >= (i - j);k --){
                    if(s[i] == s[k]){
                        dp[i][j] -= dp[k - 1][j - (i - k)];
                        dp[i][j] = (dp[i][j] + mod) % mod;
                        break;// 删除一个就好了,前面再有与i相同的数已经被当前这个k计算过了,所以不会被加入到dp[i][j] 
                    }
                }
            }
        }
        cout<<(dp[n][m] + mod) % mod<<endl;
    }
    return 0;
}
/**
Problem:
    n 个数,去除任意 m 个数,问最终能形成多少种不同的序列,对答案取模 1e9 + 7 输出
Solution:
    设 dp[i][j] = k 表示前k个数,去除 m 个有 k 种
    dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1] (dp[i - 1][j]:表示不去除第i个数;dp[i - 1][j - 1]:表示去除第i个数)
    重复现象:
        对于1,2,3,4,3,2,1,5来说,去除两个数的话会出现 (1,2,*,*,3,2,1,5),(1,2,3,*,*,2,1,5)这两种情况,而这两种得到的序列都是重复的
        因此,我们计算的时候需要避免这种情况。
        出现重复的原因就是删除连续数中存在两个相同的数,而重复的数量就是当前数a的位置为indexNow,上一次a出现的位置为indexLast,
        固定(indexLast,indexNow)区间的数字和相同的两个数其中一个(indexLast或者indexNow)一定会被删除,而剩余还需要删除的数,
        即从indexLast-1之前的数里面找j - (indxNow - indexLast))个。
        因此重复的时候状态转移方程是
        dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1] - dp[indexLast - 1][j - (i - indexLast)] 
*/