Description
你有一个长度为 $ n le 100 $ 的字符串。对于一个长度为 $ m $ 的子序列,选出它的花费是 $ n-m $,也就是你需要删掉的字符数量。你的任务是选出 $ k $ 个本质不同的子序列,使得总花费最小。输出这个最小花费。如果选不出 $ k $ 个,输出 $ -1 $。
Solution
设 (pre[i]) 表示 (i) 的前驱位置,设 (f[i][j]) 表示前 (i) 个字符,长度为 (j) 的本质不同子串的数量,则
[f[i][j]=f[i-1][j]+f[i-1][j-1]-f[pre[i]-1][j-1]
]
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 105;
int n,k,pre[N],last[N],f[N][N];
char s[N];
signed main() {
ios::sync_with_stdio(false);
cin>>n>>k>>s+1;
for(int i=1;i<=n;i++) {
pre[i]=last[s[i]-'a'];
last[s[i]-'a']=i;
}
for(int i=0;i<=n;i++) f[i][0]=1;
for(int i=1;i<=n;i++) {
for(int j=1;j<=i;j++) {
f[i][j]=f[i-1][j]+f[i-1][j-1]-(pre[i]?f[pre[i]-1][j-1]:0);
}
}
int ans=0;
for(int i=n;i>=0;--i) {
if(f[n][i]<=k) {
ans+=f[n][i]*(n-i);
k-=f[n][i];
}
else {
ans+=k*(n-i);
k=0;
break;
}
}
if(k) cout<<-1;
else cout<<ans;
}