Codeforces
CF Step
Youtube Linkedin Discord Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Code : Subsequences (hard version)

#include <bits/stdc++.h>
using namespace std;

const long long lim = 1e12;

void add(long long &a, long long delta) {
    a += delta;
    a = min(a, lim);
}

long long solve(string &str, long long k) {
    int n = str.size();
    vector<int> prev(n, -1);

    map<char, int> last_occ;
    for (int i = 0; i < n; i++) {
        if (last_occ.find(str[i]) != last_occ.end()) {
            prev[i] = last_occ[str[i]];
        }
        last_occ[str[i]] = i;
    }

    vector<vector<long long>> dp(n + 1, vector<long long>(n, 0));
    // dp[len][j] is the number of unique subsequences of len 'len' that ends
    // at index j.

    for (int i = 0; i < n; i++) {
        auto ndp = dp;
        int parent = prev[i];
        if (parent == -1) {
            ndp[1][i] = 1;
        }

        for (int len = 0; len < n; len++) {
            for (int j = 0; j < n; j++) {
                if (parent > j) {
                    continue;
                }
                add(ndp[len + 1][i], dp[len][j]);
            }
        }
        swap(ndp, dp);
    }

    // cnt[len] is the number of unique subsequences of length len.
    vector<long long> cnt(n + 1, 0);
    // Empty subsequence.
    cnt[0] = 1;
    for (int len = 0; len <= n; len++) {
        for (int j = 0; j < n; j++) {
            add(cnt[len], dp[len][j]);
        }
    }

    long long cost = 0;
    for (int len = n; len >= 0; len--) {
        if (k >= cnt[len]) {
            k -= cnt[len];
            cost += cnt[len] * (n - len);
        } else {
            cost += k * (n - len);
            k = 0;
        }
    }
    if (k == 0) {
        return cost;
    }
    return -1;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;
    long long k;
    cin >> k;
    string str;
    cin >> str;
    cout << solve(str, k) << "\n";
}
#include <bits/stdc++.h>
using namespace std;

const long long lim = 1e12;

void add(long long &a, long long delta) {
    a += delta;
    a = min(a, lim);
}

long long solve(string &str, long long k) {
    int n = str.size();

    vector<vector<long long>> dp(n + 1, vector<long long>(26, 0));
    // dp[len][ch] is the number of unique subsequences of len 'len' that ends
    // at character 'ch'.

    for (char ch : str) {
        auto ndp = dp;
        for (int len = 0; len < n; len++) {
            long long sum = 0;
            for (int j = 0; j < 26; j++) {
                add(sum, dp[len][j]);
            }
            ndp[len + 1][ch - 'a'] = sum;
        }
        ndp[1][ch - 'a'] = 1;
        swap(ndp, dp);
    }

    // cnt[len] is the number of unique subsequences of length len.
    vector<long long> cnt(n + 1, 0);
    // Empty subsequence.
    cnt[0] = 1;
    for (int len = 0; len <= n; len++) {
        for (int j = 0; j < 26; j++) {
            add(cnt[len], dp[len][j]);
        }
    }

    long long cost = 0;
    for (int len = n; len >= 0; len--) {
        if (k >= cnt[len]) {
            k -= cnt[len];
            cost += cnt[len] * (n - len);
        } else {
            cost += k * (n - len);
            k = 0;
        }
    }
    if (k == 0) {
        return cost;
    }
    return -1;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;
    long long k;
    cin >> k;
    string str;
    cin >> str;
    cout << solve(str, k) << "\n";
}
#include <bits/stdc++.h>
using namespace std;

long long solve(string &str, long long k) {
    // Switch to one based indexing.
    str = "$" + str;
    int n = str.size();
    vector<int> parent(n, -1);

    map<char, int> last_occ;
    for (int i = 0; i < n; i++) {
        if (last_occ.find(str[i]) != last_occ.end()) {
            parent[i] = last_occ[str[i]];
        }
        last_occ[str[i]] = i;
    }

    vector<vector<long long>> dp(n + 1, vector<long long>(n + 1, 0));
    // dp[i][j] is the number of distinct subsequences of length j of the
    // prefix [1 ... i]

    dp[0][0] = 1;
    for (int i = 1; i < n; i++) {
        for (int j = 0; j <= n; j++) {
            // Ignore the current element.
            dp[i][j] = dp[i - 1][j];

            if (j == 0) {
                continue;
            }
            if (dp[i][j] >= 1e18) {
                continue;
            }

            // Take the last element.
            dp[i][j] += dp[i - 1][j - 1];

            // Fix the double counting.
            if (parent[i] > 0) {
                dp[i][j] -= dp[parent[i] - 1][j - 1];
            }
        }
    }

    // cnt[len] is the number of unique subsequences of length len.
    vector<long long> cnt(n + 1, 0);
    for (int len = 0; len <= n; len++) {
        cnt[len] = dp[n - 1][len];
    }

    // Switch back to zero based indexing.
    n--;

    long long cost = 0;
    for (int len = n; len >= 0; len--) {
        if (k >= cnt[len]) {
            k -= cnt[len];
            cost += cnt[len] * (n - len);
        } else {
            cost += k * (n - len);
            k = 0;
        }
    }
    if (k == 0) {
        return cost;
    }
    return -1;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    int n;
    cin >> n;
    long long k;
    cin >> k;
    string str;
    cin >> str;
    cout << solve(str, k) << "\n";
}