HackerRank "Lucky Numbers"

Great learning for me:
https://www.hackerrank.com/rest/contests/master/challenges/lucky-numbers/hackers/turuthok/download_solution

Basically it is memorized search application. And we follow a discrete strategy: split it into digits and go digit by digit.

Here is my C++ version of the code above, with comments for easier understanding.

#include <iostream>
#include <limits>
#include <vector>
using namespace std;

typedef long long LL;

const int D = 18; // max digit count
const int MD = 9; // max single digit
const LL MAX = std::numeric_limits<LL>::max();

vector<vector<vector<LL>>> dp(D, vector<vector<LL>>(D*MD + 1, vector<LL>(D*MD*MD + 1, -1)));
vector<int> hi(D);
vector<bool> isPrime(D*MD*MD + 1, true);

LL go(int inx, int sd, int ssd, bool limited)
{
    if (inx == D) return isPrime[sd] && isPrime[ssd] ? 1 : 0;

    //    Memorized Search
    LL &ret = dp[inx][sd][ssd];
    if (!limited && ret >= 0) return ret; // We only cache unlimited count

    int upper = limited ? hi[inx] : 9;
    //    DP: count of current digit = sum of all counts of all previous digits
    LL r = 0;
    for (int i = 0; i <= upper; i++)
    {
        r += go(inx + 1, sd + i, ssd + i * i, limited && i == upper);
    }
    if (!limited) ret = r; // We only cache unlimited count
    return r;
}

LL go(LL n)
{
    if (n <= 1) return 0;

    //    split digits
    for (int i = D - 1; i >= 0; i--)
    {
        hi[i] = n % 10;
        n /= 10;
    }

    return go(0, 0, 0, true);
}

int main()
{
    // sieving
    isPrime[0] = isPrime[1] = false;
    for (int i = 2; i <= D*MD*MD; i++)
        if (isPrime[i])
            for (int j = i * 2; j <= D*MD*MD; j += i)    isPrime[j] = false;

    // go
    int t; cin >> t;
    while (t--)
    {
        LL a, b; cin >> a >> b;
        cout << (go(b) - go(a - 1)) << endl;
    }

    return 0;
}
View Code
原文地址:https://www.cnblogs.com/tonix/p/5361946.html