Question connection: http://acm.zju.edu.cn/onlinejudge/showProblem.do? Problemid = 5348
The questions of the Mudanjiang online competition were introduced during the competition, but they have never been called out. After the competition, they have also been adjusted for some time. Recently, the Code capabilities are worrying ~
There are many ways to do this. My approach is to lower the bottom of two points, that is, to determine whether there is a qualified number between low and n-1. Then greedy to construct a solution (intuition tells me that it is very troublesome to directly construct the maximum solution ).
The constructor is like this: first, let the first few digits of low and n be the same, because in any case, these digits remain unchanged. Then, if one of them is different, therefore, the lower bound is not required for the number of places to be placed in the following position. Simply greedy for the number of rows, just compare the size of the number of rows and the number of N, that is, the final problem becomes determined by the first few digits, and the total number of digits is also determined. To solve this problem, we can be greedy, but we need to enumerate where the middle part is, note that you can place 0 in the middle. For details, see the code.
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <time.h> 6 7 using namespace std; 8 typedef long long lld; 9 const int MAXN = 55; 10 const lld INF = 1LL<<62; 11 int bit[MAXN]; 12 int BIT[MAXN]; 13 lld n; 14 int m; 15 int arr[MAXN]; 16 17 lld calc(int a[], int cnt, int mid, int inx) { 18 if (2 * mid - cnt > inx) return INF; 19 lld ret = 0; 20 for (int i = m; i >= inx; i--) { 21 ret *= 10; ret += arr[i]; 22 } 23 for (int i = mid + 1; i <= cnt; i++) { 24 if (2 * mid - i <= 0 || a[i] != a[2 * mid - i]) return INF; 25 } 26 int ind = 2 * mid - cnt; 27 for (int i = inx - 1; i >= 1 && ind >= 1; i--) { 28 ret *= 10; 29 if (ind == 1) { 30 ret += a[ind]; 31 }else { 32 if (ind-1 == i || a[ind-1] <= a[ind]) { 33 ret += a[ind-1]; ind--; 34 }else { 35 ret += a[ind]; 36 } 37 } 38 } 39 return ret; 40 } 41 42 int isok(int inx) { 43 int cnt = 0; 44 int a[MAXN]; 45 for (int i = m; i >= inx; i--) { 46 if (arr[i] != 0) { 47 a[++ cnt] = arr[i]; 48 for (int j = i - 1; j >= inx; j--) { 49 if (a[cnt] != arr[j]) a[++ cnt] = arr[j]; 50 } 51 break; 52 } 53 } 54 for (int i = cnt/2; i <= cnt; i++) { 55 lld ret = calc(a, cnt, i, inx); 56 if (ret <= n) return 1; 57 } 58 a[++ cnt] = 0; 59 return calc(a, cnt, cnt, inx) <= n; 60 } 61 62 int solve() { 63 for (int i = m, fg = 0; i >= 1; i--) { 64 if (bit[i] == BIT[i] && !fg) { 65 arr[i] = bit[i]; continue; 66 } 67 int Max = (fg >= 1 ? 9 : BIT[i]); 68 for (int j = Max; j >= bit[i] + 1; j--) { 69 arr[i] = j; 70 if (isok(i)) return 1; 71 } 72 arr[i] = bit[i]; 73 fg ++; 74 } 75 int a[MAXN], cnt = 1; 76 a[1] = arr[m]; 77 for (int i = m - 1; i >= 1; i--) { 78 if (a[cnt] != arr[i]) a[++ cnt] = arr[i]; 79 } 80 for (int i = 1; i <= cnt/2; i++) { 81 if (a[i] != a[cnt-i+1]) return 0; 82 } 83 return 1; 84 } 85 86 int check(lld x) { 87 int len = 0; 88 memset(bit, 0, sizeof(bit)); 89 memset(arr, 0, sizeof(arr)); 90 while (x) { 91 bit[++ len] = x % 10; 92 x /= 10; 93 } 94 return solve(); 95 } 96 int main() { 97 int T; 98 scanf("%d", &T); 99 for (int cas = 1; cas <= T; cas++) {100 cin >> n;101 int ret;102 if (n == 1) {103 printf("0\n"); continue;104 }105 n = n - 1;106 lld l = 1, r = n;107 m = 0;108 lld tmp = n;109 while (tmp) {110 BIT[++ m] = tmp % 10;111 tmp /= 10;112 }113 while (r >= l) {114 lld mid = r + l >> 1;115 if (check(mid)) {116 l = mid + 1;117 }else {118 r = mid - 1;119 }120 }121 cout << l - 1 << endl;122 }123 return 0;124 }View code
Zoj 3816 generalized palindromic number (Binary + greedy)