Advertisement
CooBin

cntx_fc87

Sep 25th, 2018
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.38 KB | None | 0 0
  1. #include<bits/stdc++.h>
  2. #define DEBUG 0
  3. using namespace std;
  4.  
  5. typedef long long ll;
  6.  
  7. const int MOD = 2000 + 10;
  8. const int MLEN = 14;
  9.  
  10. ll mod, X, A, C;
  11.  
  12. ll dp[MLEN][MOD], num[MLEN][MOD];
  13. // dp and num as describe in solution
  14. ll special[MLEN][MOD];
  15. // special to deal with case X = 0
  16. ll p10[MLEN];
  17. // p10[i] = 10 ^ i
  18.  
  19. void init()
  20. {
  21.     // calculate p10
  22.     p10[0] = 1, p10[1] = 10;
  23.     for (int i = 2; i < MLEN; i++)
  24.         p10[i] = p10[i - 1] * p10[1];
  25.  
  26.     // base case
  27.     num[0][0] = 1;
  28.     for (int c = 0; c < 10; c++)
  29.         num[1][c % mod]++;
  30.     dp[1][X % mod]++;
  31.  
  32.     // calculate bottom up
  33.     for (int len = 1; len + 1 < MLEN; len++)
  34.         for (int pmod = 0; pmod < MOD; pmod++)
  35.         {
  36.             // special have to take from its child
  37.             special[len][pmod] += special[len - 1][pmod];
  38.             for (int c = 0; c < 10; c++)
  39.             {
  40.                 ll newMod = (pmod + c * p10[len] ) % mod;
  41.                 num[len + 1][newMod] += num[len][pmod];
  42.                 dp[len + 1][newMod] += dp[len][pmod];
  43.                 if (c) special[len + 1][newMod] += dp[len][pmod];
  44.                 if (c == X) dp[len + 1][newMod] += num[len][pmod];
  45.             }
  46.         }
  47. }
  48.  
  49. ll F(ll lim)
  50. {
  51.     if (lim < 0) return 0;
  52.     // indigit is lim in string
  53.     vector<int > indigit;
  54.     ll cloneLim = lim;
  55.     while (cloneLim)
  56.         indigit.push_back(cloneLim % 10),
  57.         cloneLim /= 10;
  58.  
  59.     ll result = 0;
  60.     // accumulate = number of X from indigit.size() - 1 to cid + 1
  61.     // currentNum = actual number from indigit.size() - 1 to cid + 1
  62.     // to understand better, read the code below
  63.     int accumulate = 0; ll currentNum = 0;
  64.  
  65.     for (int cid = indigit.size() - 1; cid >= 0; cid--)
  66.     {
  67.         // current digit
  68.         int digit = indigit[cid];
  69.         int start = 0;
  70.         if (!X && cid == indigit.size() - 1) start = 1;
  71.  
  72.         for (int foo = start; foo < digit; foo++)
  73.         {
  74.             int remLen = cid;
  75.             // calculate remainMod
  76.             ll currentMod = ( currentNum * p10[remLen + 1] + foo * p10[remLen] ) % mod;
  77.             ll remainMod  = A % mod - currentMod;
  78.             if (remainMod < 0) remainMod += mod;
  79.  
  80.             result += dp[remLen][remainMod];
  81.             result += (accumulate + (foo == X)) * num[remLen][remainMod];
  82.         }
  83.         accumulate += (digit == X);
  84.         currentNum = currentNum * 10 + digit;
  85.     }
  86.     // special case when X == 0
  87.     if (!X) result += special[indigit.size() - 1][A % mod];
  88.     return result;
  89. }  
  90.  
  91. main()
  92. {  
  93.     if (fopen("main.in", "r"))
  94.         freopen("main.in", "r", stdin);
  95.     cin >> A >> mod >> C >> X;
  96.  
  97.     init();
  98.  
  99.     ll L = A, R = A + mod * C;
  100.     cout << F(R + 1) - F(L) << '\n';
  101. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement