fork(1) download
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int maxDigits = 105;
  5. const int maxDiv = 100*1000 + 5;
  6. string target; // N
  7. int divi; // M
  8. int nbDigits; // D
  9. int dp[maxDigits][maxDiv]; // i first digits set, current val (X mod M) = j
  10. int pow10[maxDigits];
  11.  
  12. int main()
  13. {
  14. ios::sync_with_stdio(false);
  15. cin.tie(0);
  16.  
  17. cin >> target >> divi;
  18. nbDigits = target.size();
  19. for (int valMod = 1; valMod < divi; ++valMod) {
  20. dp[nbDigits][valMod] = maxDigits; // Considered to be INF
  21. }
  22. dp[nbDigits][0] = 0; // Final state we must reach
  23.  
  24. pow10[0] = 1;
  25. for (int expo = 1; expo < maxDigits; ++expo) {
  26. pow10[expo] = (pow10[expo-1] * 10) % divi;
  27. }
  28.  
  29. // Slow part
  30. for (int iDigit = nbDigits-1; iDigit >= 0; --iDigit) {
  31. int targetDigit = (target[iDigit] - '0');
  32. int corPow = pow10[nbDigits-1-iDigit];
  33. for (int origVal = 0; origVal < divi; ++origVal) {
  34. int res = maxDigits;
  35. int newVal = origVal;
  36. for (int digitChoice = 0; digitChoice < 10; ++digitChoice) {
  37. if (iDigit > 0 || digitChoice > 0) { // Don't put a leading 0!
  38. int subRes = dp[iDigit+1][newVal];
  39. if (digitChoice != targetDigit) ++subRes;
  40. if (subRes < res) res = subRes;
  41. }
  42.  
  43. // Avoid multiplying, add at each iteration instead!
  44. newVal += corPow;
  45. // Avoid modulo, substract instead! (faster)
  46. if (newVal >= divi) newVal -= divi;
  47. }
  48. dp[iDigit][origVal] = res;
  49. }
  50. }
  51.  
  52. // Reconstruction of X
  53. string answer;
  54. int curDigit = 0, curVal = 0;
  55. while (curDigit < nbDigits) {
  56. int targetDigit = (target[curDigit] - '0');
  57. int opt = -1;
  58. int corPow = pow10[nbDigits-1-curDigit];
  59.  
  60. for (int digitChoice = 9; digitChoice >= 0; --digitChoice) { // Decreasing order -> put minimal optimal digit
  61. int newVal = (curVal + digitChoice*corPow)%divi;
  62. if (curDigit > 0 || digitChoice > 0) {
  63. int subRes = dp[curDigit+1][newVal];
  64. if (digitChoice != targetDigit) ++subRes;
  65. if (dp[curDigit][curVal] == subRes) {
  66. opt = digitChoice;
  67. }
  68. }
  69. }
  70.  
  71. answer.push_back(opt + '0');
  72. ++curDigit;
  73. curVal = (curVal + opt*corPow)%divi;
  74. }
  75.  
  76. cout << answer << '\n';
  77. }
  78.  
Success #stdin #stdout 0.26s 42676KB
stdin
748062708555281153846851854457124509225088457204956207420175239499881412315482099388504785561611375 99763
stdout
748062708525281153846851854457124509225088457204956207420175239499881412315582099388504785561611375