思路:
dp好题,dp[i][j]表示到前i个字符为止并且以s[i]为结尾,共有多少个长度为j的不同的子序列。
实现:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 ll dp[105][105], sum[105]; 5 int last[30]; 6 int main() 7 { 8 int n; ll m; string s; 9 while (cin >> n >> m >> s) 10 { 11 memset(dp, 0, sizeof dp); 12 memset(sum, 0, sizeof sum); 13 memset(last, -1, sizeof last); 14 for (int i = 1; i <= n; i++) 15 { 16 dp[i][1] = 1; 17 for (int j = 2; j <= i; j++) 18 { 19 for (int k = 0; k < 26; k++) 20 { 21 if (last[k] != -1) 22 { 23 int p = last[k]; 24 dp[i][j] += dp[p][j - 1]; 25 } 26 } 27 } 28 last[s[i - 1] - 'a'] = i; 29 } 30 for (int i = 1; i <= n; i++) 31 { 32 for (int j = 0; j < 26; j++) 33 { 34 if (last[j] != -1) sum[i] += dp[last[j]][i]; 35 } 36 } 37 sum[0] = 1; 38 ll ans = 0; 39 bool flg = false; 40 for (int i = n; i >= 0; i--) 41 { 42 if (m - sum[i] <= 0) { ans += m * ((ll)n - i); flg = true; break; } 43 ans += sum[i] * ((ll)n - i); m -= sum[i]; 44 } 45 cout << (flg ? ans : -1) << endl; 46 } 47 return 0; 48 }