题意:
给出一个字符串删除一些字符使得子串个数是K,并且代价最小,代价为删除的字符数量。
分析:
表示前i个字符,删除j个后一共有多少种情况
如果不考虑重复很容易得出 即当前字符删不删两种情况
如果有重复的话,比如abcdgefg ,下标从1开始,那么i=8与k=5相同,如果当前删除的字符是j=3个的话,那么删除 gef 和删除 efg
所得的结果相同。多算了abcdg一次,即多算了abcd一次,那么减去这个字符串的贡献即可,易得贡献为
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=105;
ll dp[maxn][maxn];
char s[maxn];
int pre[30];
int main(){
int n;
ll k;
scanf("%d%lld",&n,&k);
scanf("%s",s+1);
dp[0][0]=1ll;
for(int i=1;i<=n;i++){
dp[i][0]=1ll;
for(int j=1;j<=i;j++){
dp[i][j]+=dp[i-1][j-1]+dp[i-1][j];
if(pre[s[i]-'a']&&j>=(i-pre[s[i]-'a'])) dp[i][j]-=dp[pre[s[i]-'a']-1][j-(i-pre[s[i]-'a'])];
if(dp[i][j]>k) dp[i][j]=k;
}
pre[s[i]-'a']=i;
}
ll ans=0;
for(int i=0;i<=n;i++){
ans+=min(dp[n][i],k)*(ll)i;
k-=dp[n][i];
if(k<=0) break;
}
if(k>0) printf("-1\n");
else printf("%lld\n",ans);
return 0;
}