最小回文数

· · 题解

这道题好 difficult。

为了不让下面的各位大佬与我相提并论的想法相同,我整整花了8,9个小时的休息时间,才得以做出来,所以我想吐槽一下说一下我的艰辛,希望大家能谅解!!!

好了,正式进入主题。

其实这道题难归难,其实也有更简单的方法,可以不用高精,特别是枚举,想都别想,如果枚举最坏的情况可不是我们能预料的,所以我们要用的是关于回文数的特性,顺读法和逆读法相等 这不废话吗

嗯嗯!!!这道题我们就是要用回文数的特性来找规律,不妨给大家举个例子:

ABCDEFGHABCDEFG

我们以这两个来进行分析。

首先根据回文数的特性,我们可以得出,如果是 ABCDEFGH 要变成回文数,可以变成为 ABCDDCBA,或者 HGFEEFGH 对不对?没错,ABCDEFG 也是同理的。这就是第一步“变”。就是先把它变成回文数。但是代码如何实现呢???其实也很简单,不过本人更喜欢 ABCDDCBA 这一种,所以上代码吧:

    int len,i;
    for(i=len-1;i>=floor(len/2);i--)//这里我们之所以支循环到floor(len/2)是因为,如果len为8,那么这是属于ABCDEFGH这个类型,那么各个数在字符数组的位置为0,1,2,3,4,5,6,7,所以我们只需要循环到4这个地方(以为我们是要把4,5,6,7上的数改换为3,2,1,0上的数)
        b[i]=b[len-1-i];//现在就开始转换,把7,6,5,4上的数让0,1,2,3也与其相同。

大家如果未弄懂的话,一定要弄懂,否则下面的程序和思路将会看不懂。

好!现在换位成回文数已经做好了,那么我们现在就进行下一步,比较!比较什么呢,大家仔细想一想,我们的回文数必须得大于原数,所以我们要判断这个原本的 ABCDEFGH 和我们创造出来的 ABCDDCBA 的大小关系,如果是 ABCDEFGH 小于 ABCDDCBA 自然是最好的,直接输出就行,无需作太多处理,但是如果是大于或者小于该怎么办了,不要慌。我们再想一下并且看一下 ABCDEFGHABCDEFGH,看清楚了吗,想清楚了吗???我想以大家的聪明才智一定已经想出来了,没错,我们只需要在 ABCDDCBA 上面加一就可以了,有些人会问为什么不在 AA 上面加了,大家仔细想一下就清楚了,如果是 AA 加最右边的 A 加起来确实是最少的,但追左边的 A 加起来可就大了,所以我们要加的是 DD

大家看到这里是不是感觉已经完了,不不不不,还有一种特殊情况,如果 DD 上为 99 呢,这个可就麻烦大了,也不要慌,这里需要用到一小丢丢的高精度,其实也不算高精度,只不过是进位罢了,这个比较也简单,不过忘记讲了,这个可以用一个专门用来比较字符串的函数,代码中会给大家介绍。好了,我们再想一下如果说这个 DD99,是会对我们的结果有一定的影响的,大家看好了:

如果说 ABCDDCBA12399321,那么经过我们的操作后就会变成 12410321,并不是一个回文数对吧,也不要慌,我们再来一次就行了(再来一次“变”)因为再“变”时,就不会在 DD 上有 9 了。不过也没完,因为还有一个数要特判,如果说全部数都为 9,也就是 99999999,按我们的方法来处理,就变成了 100010999,但最简的答案是 100000001,所以这种凡是全部数都为 9 的都要特判。代码如下:

    int ans1=0,k;//用来统计9在数中出现的次数。k用来保存中间数再数组中的坐标。
    for(i=0;i<len;i++){
        b[i]=a[i];
        if(b[i]=='9') ans1++;//统计9在数中出现的次数。
    }
    if(ans1==len){//如果全部都为9
        for(i=1;i<len;i++)
            b[i]='0';//那么就把ABCDDCBA中的ABCDDCB变为0000000。
        len++;
        b[len-1]='1';
        b[0]='1';//A变为1,再在ABCD的前面加一个E为1,就变成了100000001。
    }
    if(strcmp(b,a)<=0){
            k=floor(len/2);//用k来保存中间数再数组中的坐标。
            if(len%2==0){
                b[k]=(char)b[k]+1;
                b[k-1]=(char)b[k-1]+1;//就在它的中间部位上的数加1。
            }
            else b[k]=(char)b[k]+1;
            for(i=0;i<len;i++){
                if(b[i]>'9'){
                    b[i]=(char)b[i]-10;
                    b[i+1]=(char)b[i+1]+1;
                } 
            }
            if(b[len]>'0') len++;
            for(i=len-1;i>=floor(len/2);i--)
                b[len-1-i]=b[i];
        }

好了全代码为:

#include<bits/stdc++.h>
const int MAX=11000;
using namespace std;
char a[MAX],b[MAX];
int main(){
    int i,len,k,ans1=0;
    scanf("%s",a);
    len=strlen(a);
    for(i=0;i<len;i++){
        b[i]=a[i];
        if(b[i]=='9') ans1++;
    }
    if(ans1==len){
        for(i=1;i<len;i++)
            b[i]='0';
     len++;
        b[len-1]='1';
        b[0]='1';
    }
    else{
        for(i=len-1;i>=floor(len/2);i--)
        b[i]=b[len-1-i];
        if(strcmp(b,a)<=0){
            k=floor(len/2);
            if(len%2==0){
                b[k]=(char)b[k]+1;
                b[k-1]=(char)b[k-1]+1;
            }
            else b[k]=(char)b[k]+1;
            for(i=0;i<len;i++){
                if(b[i]>'9'){
                    b[i]=(char)b[i]-10;
                    b[i+1]=(char)b[i+1]+1;
                } 
            }
            if(b[len]>'0') len++;
            for(i=len-1;i>=floor(len/2);i--)
              b[i]=b[len-1-i];
        }
    }
    for(i=0;i<len;i++)//输出。
        printf("%c",b[i]);
    return 0;
} 

//不用说谢谢,不因客套,只因能见您的笑容,以及您电脑上的 AC,您已经回报。

//祝大家信息学越来越棒哦!