zoj 3816 Generalized Palindromic Number (二分+贪心)

题目连接 : http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5348

牡丹江网络赛的题,比赛的时候想到做法的,但是一直没调出来,赛后也调了些时间,最近代码能力堪忧啊~

有好多做法, 我的做法是二分下界low,即判断在low到n-1之间是否存在符合要求的数。然后贪心去构造一个解(直觉告诉我直接构造最大解好像很麻烦的样子)。

构造解是这样的:首先low和n相同的前几位先放好,因为不管怎样这几位都是不变的,然后假如某一位不相同了,那么后面的位置上放数就不需要考虑下界了,直接贪心出最小解就行了,比较最小解与N的大小就行了,也就是最后问题变成了前几位确定的,总的位数也是确定的,求最小解,这个可以贪心搞的,不过需要枚举中间在哪里,注意可以在中间放0喔。具体细节看代码。

  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 }

时间: 2024-08-03 11:18:09

zoj 3816 Generalized Palindromic Number (二分+贪心)的相关文章

zoj 3816 Generalized Palindromic Number(暴力枚举)

题目链接:zoj 3816 Generalized Palindromic Number 题目大意:给定n,找一个最大的数x,保证x小于n,并且x为palindromic number 解题思路:枚举前i个放于n相同的数,然后去构造后半部分即可. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef unsigned long long ll; int

ZOJ - 3816 Generalized Palindromic Number

Description A number that will be the same when it is written forwards or backwards is known as a palindromic number. For example, 1234321 is a palindromic number. We call a number generalized palindromic number, if after merging all the consecutive

ZOJ - 3816 Generalized Palindromic Number dfs

Generalized Palindromic Number Time Limit: 2 Seconds                                     Memory Limit: 65536 KB A number that will be the same when it is written forwards or backwards is known as a palindromic number. For example, 1234321 is a palind

zoj 3816 Generalized Palindromic Number (根据对称性来搜)

Generalized Palindromic Number Time Limit: 2 Seconds      Memory Limit: 65536 KB A number that will be the same when it is written forwards or backwards is known as a palindromic number. For example, 1234321 is a palindromic number. We call a number

[ACM] ZOJ 3816 Generalized Palindromic Number (DFS,暴力枚举)

Generalized Palindromic Number Time Limit: 2 Seconds      Memory Limit: 65536 KB A number that will be the same when it is written forwards or backwards is known as a palindromic number. For example, 1234321 is a palindromic number. We call a number 

ZOJ 3816 Generalized Palindromic Number dfs+暴力枚举

题目链接:点击打开链接 题意: 给定一个数n 找一个最大的数u使得u<n && u为回文. 枚举前面有多少位是一样的.然后分类讨论.啪啦啪啦 #include <cstdio> #include <algorithm> #include <cstring> #include <iostream> #include <vector> using namespace std; typedef long long ll; cons

[数位dp+二分] zoj Generalized Palindromic Number

题意: 找一个小于N的最大的且符合题意的数. 题意的数为,通过缩减后是回文的数,所谓的缩减就是相同连续的数看做一个数,如"155451111"其实就是"15451"是符合题意的数. 思路: 通过数位dp,然后二分求解. dp[i][j][k]代表第i位,已经放了j个数,最后长度是k的缩减回文数有几个. 然后需要一个ok[]数组代表放的数是什么,如果连续放相同的数就等于没放数. 遍历所有的长度就可以得到结果了. 其实不难发现,这种回文数一定是奇数位的. 代码: #in

ZOJ 4062 - Plants vs. Zombies - [二分+贪心][2018 ACM-ICPC Asia Qingdao Regional Problem E]

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4062 题意: 现在在一条 $x$ 轴上玩植物大战僵尸,有 $n$ 个植物,编号为 $1 \sim n$,第 $i$ 个植物的位置在坐标 $i$,成长值为 $a_i$,初始防御值为 $d_i$. 现在有一辆小车从坐标 $0$ 出发,每次浇水操作必须是先走 $1$ 单位长度,然后再进行浇水,植物被浇一次水,防御值 $d_i+=a_i$. 现在知道,小车最多进行 $m

Mudangjiang Online H Generalized Palindromic Number

一开始觉得是数位DP,后来想不出来. 但是感觉爆搜+剪枝可以过,于是就过了.. #include <cstdio> #include <algorithm> #include <cstring> using namespace std; typedef long long LL; const int maxn = 50; int lim[maxn], len; LL num; void getlim(LL n) { memset(lim, 0, sizeof(lim))