解析:
设f[i][j]:表示选第i个字符,长度为k的且本质不同的子序列方案数
状态方程:f[i][j]=f[i-1][j]+f[i-1][j-1] 不选s[i]/选s[i]
但是会有重复的,我们用last记录字符之前出现过的位置。然后减去那部分
f[i][j]-=f[last-1][j-1]
f[last-1][j-1] 就相当于重复的方案数加上第i个字符
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+100;
const int MOD=1e9+7;
typedef long long ll;
ll f[N][N];
int n,k;
int last[N];
char s[N];
int main()
{
scanf("%d %d",&n,&k);
cin>>(s+1);
f[0][0]=1;
for(int i=1;i<=n;i++)
{
f[i][0]=1;
for(int j=1;j<=i;j++)
{
//没选s[i],和选了s[i]
f[i][j]=f[i-1][j]+f[i-1][j-1];//总和,有可能包括重复的
if(last[s[i]-'a']) f[i][j]-=f[last[s[i]-'a']-1][j-1];
f[i][j]=(f[i][j]+MOD)%MOD;
}
last[s[i]-'a']=i;
}
cout<<f[n][k]<<endl;
}