[关闭]
@sztom 2019-08-25T13:46:16.000000Z 字数 3628 阅读 120

T2 题解 - 最近回文数

Exam02


题目:

题目背景

小X最近闲来无事,开始切水题。
他看到 最近回文数 这道题,轻松打了一个数位dp。
然而他觉得数位dp有点小题大做了,想了想,用一个简单的算法,瞬间AC。
他觉得非常有趣,边来考考大家。(小X不是我,他的出处是 P2107 小Z的AK计划

题目描述

输入一个整数,找到与它的差的绝对值最小的回文数。当有两个解时,取较小的那一个解。

输入格式

输入为一行,包括一个整数

输出格式

输出只有一个整数,为与输入数字的差的绝对值最小的回文数。

样例输入

10000

样例输出

9999

数据范围

对于 的数据,
对于 的数据,
对于 的数据,

乍看似乎不难:

算法(简单)

枚举差的绝对值,逐个判断是否是回文数,直到找到回文数为止。

仔细审题发现 的长度至多为位,而 long long 也才约

可以用字符串模拟大整数。

写出代码:

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. string plus_one(string n) {
  5. string back = n;
  6. int last_number = (int)n[n.size() - 1] - '0';
  7. if (last_number < 9) {
  8. back[back.size() - 1] = (char)((int)back[back.size() - 1] + 1);
  9. } else {
  10. int i = n.size() - 1;
  11. while (last_number == 9 && i > 0) {
  12. back[i] = '0';
  13. i--;
  14. last_number = back[i] - '0';
  15. }
  16. if (last_number != 9) {
  17. back[i] = (char)((int)back[i] + 1);
  18. } else {
  19. back[0] = '1';
  20. back = back + '0';
  21. }
  22. }
  23. return back;
  24. }
  25. string minus_one(string n) {
  26. string back = n;
  27. int last_number = (int)n[n.size() - 1] - '0';
  28. if (last_number > 0) {
  29. back[back.size() - 1] = (char)((int)back[back.size() - 1] - 1);
  30. } else {
  31. int i = n.size() - 1;
  32. while (last_number == 0 && i > 0) {
  33. back[i] = '9';
  34. i--;
  35. last_number = back[i] - '0';
  36. }
  37. if (last_number != 1) {
  38. back[i] = (char)((int)back[i] - 1);
  39. }
  40. }
  41. return back;
  42. }
  43. bool repet(string n) {
  44. string backn;
  45. for (int i = 0; i < n.size()/2; i++) {
  46. if (n[i] != n[n.size() - i - 1]){
  47. return false;
  48. }
  49. }
  50. return true;
  51. }
  52. int main() {
  53. string n;
  54. cin >> n;
  55. string plus_n = n;
  56. string minus_n = n;
  57. if (repet(n)){
  58. cout << n << endl;
  59. return 0;
  60. }
  61. while(minus_n.size() > 1){
  62. minus_n = minus_one(minus_n);
  63. if (true == repet(minus_n)){
  64. cout << minus_n << endl;
  65. break;
  66. }
  67. plus_n = plus_one(plus_n);
  68. if (true == repet(plus_n)){
  69. cout << plus_n << endl;
  70. break;
  71. }
  72. }
  73. return 0;
  74. }

不要忘了时间限制(1000ms),对于超过的数会非常慢。

我们需要一个效率高的算法:

算法(最终)

一位一位判断:

条件Condition

A1-如果高位小于低位且低位减高位小于等于5
A2-如果高位小于低位且低位减高位大于5
B1-如果高位不小于低位且高位减低位小于5
B2-如果高位不小于低位且高位减低位不小于5

做法Action

A1:低位赋值为高位 e.g. 155->151
A2:低位赋值为高位,低+1位+1 e.g. 159->161
B1:低位赋值为高位 e.g. 451->454
B2:低位赋值为高位,低+1位-1 e.g. 751->747

最终代码:

  1. #include <iostream>
  2. #include <string>
  3. using namespace std;
  4. string write_c(int t, char a) {
  5. string back = "";
  6. for (int i = 0; i < t; i++) {
  7. back += a;
  8. }
  9. return back;
  10. }
  11. string plus_one(string n) {
  12. string back = n;
  13. int last_number = (int)n[n.size() - 1] - '0';
  14. if (last_number < 9) {
  15. back[back.size() - 1] = (char)((int)back[back.size() - 1] + 1);
  16. } else {
  17. int i = n.size() - 1;
  18. while (last_number == 9 && i > 0) {
  19. back[i] = '0';
  20. i--;
  21. last_number = back[i] - '0';
  22. }
  23. if (last_number != 9) {
  24. back[i] = (char)((int)back[i] + 1);
  25. } else {
  26. back[0] = '1';
  27. back = back + '0';
  28. }
  29. }
  30. return back;
  31. }
  32. string sub_one(string n) {
  33. string back = n;
  34. int last_number = (int)n[n.size() - 1] - '0';
  35. if (last_number > 0) {
  36. back[back.size() - 1] = (char)((int)back[back.size() - 1] - 1);
  37. } else {
  38. int i = n.size() - 1;
  39. while (last_number == 0 && i > 0) {
  40. back[i] = '9';
  41. i--;
  42. last_number = back[i] - '0';
  43. }
  44. if (last_number != 1) {
  45. back[i] = (char)((int)back[i] - 1);
  46. }
  47. }
  48. return back;
  49. }
  50. bool one_with_zero(string s) {
  51. if (s[0] != '1') {return false;}
  52. if (s == "1") {return false;}
  53. for (int i = 1; i < s.size(); i++) {
  54. if (s[i] != '0') {
  55. return false;
  56. }
  57. }
  58. return true;
  59. }
  60. string A1(string n, int high, int low) {
  61. n[low] = n[high];
  62. return n;
  63. }
  64. string A2(string n, int high, int low) {
  65. n = A1(n, high, low);
  66. string need_plus = n.substr(0, low);
  67. string other = n.substr(low);
  68. need_plus = plus_one(need_plus);
  69. n = need_plus + other;
  70. return n;
  71. }
  72. string B1(string n, int high, int low) {
  73. n[low] = n[high];
  74. return n;
  75. }
  76. string B2(string n, int high, int low) {
  77. n = A1(n, high, low);
  78. string need_sub = n.substr(0, low);
  79. string other = n.substr(low);
  80. need_sub = sub_one(need_sub);
  81. n = need_sub + other;
  82. return n;
  83. }
  84. int main() {
  85. string n;
  86. cin >> n;
  87. string ans = n;
  88. int high = 0, low = n.size() - 1;
  89. if (one_with_zero(n)) {
  90. ans = write_c(n.size() - 1, '9');
  91. cout << ans << endl;
  92. return 0;
  93. }
  94. while ((low - high) >= 1) {
  95. if (ans[high] == ans[low]) {
  96. high++;
  97. low--;
  98. continue;
  99. }
  100. if (ans[high] < ans[low]) { // enter A
  101. if ((ans[low] - ans[high]) <= 5) {
  102. ans = A1(ans, high, low);
  103. } else {
  104. ans = A2(ans, high, low);
  105. }
  106. } else { // enter B
  107. if ((ans[high] - ans[low]) < 5) {
  108. ans = B1(ans, high, low);
  109. } else {
  110. ans = B2(ans, high, low);
  111. }
  112. }
  113. }
  114. cout << ans << endl;
  115. return 0;
  116. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注