Challenge: k-balance number

Subdomeniu: Combinatorics (combinatorics)

Scor cont: 100.0 / 100

Submission status: Accepted

Submission score: 1.0

Submission ID: 464815975

Limbaj: cpp14

Link challenge: https://www.hackerrank.com/challenges/k-balance/problem

Cerinta

Your task is to calculate the sum (indicated by S) of all the k-balanced integers between [L, R]. An integer is called k-balanced when either of #1 or #2 below holds true.

1. The length of the integer <= k     
2. Sum of the first k digits (with no leading zeros) is equal to the sum of the last k digits.    

**Input format**  
L R k

**Output format**  
S % 1000000007

**Constraints**  
0 < L <= R < 10^18  
0 < k <= 18

**Sample Input**  
9 23 1

**Sample Output**  
42

**Explanation**  
9, 11 and 22 are the only 3 integers between 9 and 23 ( both included ) that are k-balanced. Hence, the answer is 9+11+22=42

Cod sursa

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

static const int MOD = 1000000007;

struct Node {
    int cnt;
    int sum;
};

static inline int addm(int a, int b) {
    a += b;
    if (a >= MOD) a -= MOD;
    return a;
}

static inline int subm(int a, int b) {
    a -= b;
    if (a < 0) a += MOD;
    return a;
}

static inline int mulm(long long a, long long b) {
    return (int)((a * b) % MOD);
}

static int solve_len_any(int len, const vector<int>* lim) {
    // All numbers with exactly len digits (first non-zero), optionally <= lim.
    array<Node,2> cur{}, nxt{};
    cur[1] = {1, 0};

    for (int pos = 0; pos < len; ++pos) {
        nxt = {};
        for (int tight = 0; tight <= 1; ++tight) {
            int cnt = cur[tight].cnt;
            int sm = cur[tight].sum;
            if (!cnt && !sm) continue;

            int md = (tight && lim) ? (*lim)[pos] : 9;
            int lo = (pos == 0 ? 1 : 0);
            for (int d = lo; d <= md; ++d) {
                int nt = (tight && lim && d == md) ? 1 : 0;
                int ncnt = addm(nxt[nt].cnt, cnt);
                int nsum = nxt[nt].sum;
                nsum = addm(nsum, mulm(sm, 10));
                nsum = addm(nsum, mulm(cnt, d));
                nxt[nt] = {ncnt, nsum};
            }
        }
        cur = nxt;
    }

    int ans = 0;
    if (lim) ans = addm(cur[0].sum, cur[1].sum);
    else ans = cur[0].sum;
    return ans;
}

static int solve_len_balanced(int len, int k, const vector<int>* lim) {
    // len > k. Need sum(first k digits) == sum(last k digits).
    int maxAbs = 9 * k;
    int W = 2 * maxAbs + 1;
    int OFF = maxAbs;

    vector<array<Node,2>> cur(W), nxt(W);
    cur[OFF][1] = {1, 0};

    auto coeff = [&](int pos) {
        int c = 0;
        if (pos < k) c += 1;
        if (pos >= len - k) c -= 1;
        return c;
    };

    for (int pos = 0; pos < len; ++pos) {
        for (int i = 0; i < W; ++i) nxt[i] = {};
        int cf = coeff(pos);

        for (int di = 0; di < W; ++di) {
            for (int tight = 0; tight <= 1; ++tight) {
                int cnt = cur[di][tight].cnt;
                int sm = cur[di][tight].sum;
                if (!cnt && !sm) continue;

                int md = (tight && lim) ? (*lim)[pos] : 9;
                int lo = (pos == 0 ? 1 : 0);
                for (int d = lo; d <= md; ++d) {
                    int ndi = di + cf * d;
                    if (ndi < 0 || ndi >= W) continue;
                    int nt = (tight && lim && d == md) ? 1 : 0;

                    int ncnt = addm(nxt[ndi][nt].cnt, cnt);
                    int nsum = nxt[ndi][nt].sum;
                    nsum = addm(nsum, mulm(sm, 10));
                    nsum = addm(nsum, mulm(cnt, d));
                    nxt[ndi][nt] = {ncnt, nsum};
                }
            }
        }
        cur.swap(nxt);
    }

    int ans = 0;
    if (lim) ans = addm(cur[OFF][0].sum, cur[OFF][1].sum);
    else ans = cur[OFF][0].sum;
    return ans;
}

static int solve_upto(long long X, int k) {
    if (X <= 0) return 0;
    string s = to_string(X);
    int n = (int)s.size();

    int ans = 0;
    for (int len = 1; len < n; ++len) {
        if (len <= k) ans = addm(ans, solve_len_any(len, nullptr));
        else ans = addm(ans, solve_len_balanced(len, k, nullptr));
    }

    vector<int> lim(n);
    for (int i = 0; i < n; ++i) lim[i] = s[i] - '0';
    if (n <= k) ans = addm(ans, solve_len_any(n, &lim));
    else ans = addm(ans, solve_len_balanced(n, k, &lim));

    return ans;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    long long L, R;
    int k;
    cin >> L >> R >> k;

    int ans = subm(solve_upto(R, k), solve_upto(L - 1, k));
    cout << ans << '\n';
    return 0;
}
HackerRank Combinatorics – k-balance number