Advertisement
VictorXjoeY

Dynamic programming approach

Nov 15th, 2019
252
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.09 KB | None | 0 0
  1. #include <cstdio>
  2. #include <vector>
  3.  
  4. using namespace std;
  5.  
  6. constexpr int N = 1000000000;
  7. constexpr int P = 10; // Maximum number of digits in N.
  8.  
  9. bool seen[P + 1][13 + 1][2][2][2];
  10. int dp[P + 1][13 + 1][2][2][2];
  11. vector<int> d;
  12.  
  13. /* Returns the number of unlucky numbers up to N. States are:
  14. p = Current digit index (0 <= p <= 10)
  15. sum = Current digit sum (0 <= sum <= 13)
  16. lesser = True if the current number being constructed is already strictly lesser than N.
  17. last = True if the last digit of the current number being constructed was a 1.
  18. has = True if the current number being constructed already has a 13 as a substring. */
  19. int solve(int p, int sum, bool lesser, bool last, bool has) {
  20.     if (p < 0) {
  21.         return has and sum == 0; // The constructed number is unlucky if it has 13 as a substring and the sum is 13.
  22.     }
  23.  
  24.     if (seen[p][sum][lesser][last][has]) {
  25.         return dp[p][sum][lesser][last][has];
  26.     }
  27.  
  28.     seen[p][sum][lesser][last][has] = true;
  29.     dp[p][sum][lesser][last][has] = 0;
  30.  
  31.     for (int i = 0; i <= min((lesser ? 9 : d[p]), sum); i++) {
  32.         dp[p][sum][lesser][last][has] += solve(p - 1, sum - i, lesser or i < d[p], i == 1, has or (last and i == 3));
  33.     }
  34.  
  35.     return dp[p][sum][lesser][last][has];
  36. }
  37.  
  38. /* Prints all the unlucky numbers up to N in ascending order. */
  39. void generate(int cur, int p, int sum, bool lesser, bool last, bool has) {
  40.     if (p < 0) {
  41.         printf("%d\n", cur);
  42.         return;
  43.     }
  44.  
  45.     for (int i = 0; i <= min((lesser ? 9 : d[p]), sum); i++) {
  46.         // Only traverses to another state if there's a positive amount of unlucky numbers going through that state.
  47.         if (solve(p - 1, sum - i, lesser or i < d[p], i == 1, has or (last and i == 3)) > 0) {
  48.             generate(10 * cur + i, p - 1, sum - i, lesser or i < d[p], i == 1, has or (last and i == 3));
  49.         }
  50.     }
  51. }
  52.  
  53. int main() {
  54.     int n;
  55.  
  56.     scanf("%d", &n);
  57.  
  58.     // Extracting the digits of n.
  59.     while (n > 0) {
  60.         d.push_back(n % 10);
  61.         n /= 10;
  62.     }
  63.  
  64.     // Printing the unlucky numbers up to n in ascending order.
  65.     printf("%d\n", solve(d.size() - 1, 13, false, false, false));
  66.     generate(0, d.size() - 1, 13, false, false, false);
  67.  
  68.     return 0;
  69. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement