幼稚园的数学Ⅱ | ||||||
|
||||||
Description | ||||||
唉。。自从上次被幼儿园数学虐残之后,小胖子koko觉得自己要开始练习幼儿园数学了,于是他就像幼儿园传奇教父 AK_PUSH前辈请教。 AK_PUSH前辈为了看看小胖子koko是否具有学习幼儿园数学的潜质,给他出了一道题目:给你一个数N找出第一个比N大的回文数。一个数被称为回文数,当且仅当。。。它正反念都一样啦!小胖子koko看了题后haha大笑,这题未免也太水了吧!于是他花了10秒钟写就写完了程序,然后。。。他就来找你炫耀啦! 为了避免被幼儿园小朋友暴虐,你的任务就是,写一个程序,完成 AK_PUSH前辈的题目。 |
||||||
Input | ||||||
输入以T开始,代表测试样例的个数(T<=30),每组样例包括一个整数:n(n<10^50000) | ||||||
Output | ||||||
每一组样例,输出符合条件的最小回文数 | ||||||
Sample Input | ||||||
5 121 1 1332331 11 1121 |
||||||
Sample Output | ||||||
Case 1: 131 Case 2: 2 Case 3: 1333331 Case 4: 22 Case 5: 1221 |
||||||
Author | ||||||
小伙伴们@哈商大 |
题意:求第一个比N大的回文数(N可以是非回文数或回文数)
思路:
这题十分抠细节
假设第一个比N大的回文数是M
△必须达到最小(△=M-N)即增量最小
在改变N的其中一对数字时候从中间开始往左右改数字增量一定是最小的
比如10001可变成10101 11011 明显能看到从中间开始该数字的增量是最小的
因为高位数字的增量一定比低位数字的增量大
修改数字的时候还要注意一些细节
首先要从中间往左右遍历,找出第一对不相等的数字Ai Aj(Ai在高位,Aj在低位),如果Ai>Aj那么把Aj改为Ai(理由见红字),否则把两个数都改为Ai+1,然后剩下每一对不相等的数字Ai Aj都改为Ai Ai
为什么要剩下的每一对都改成和Ai一样的呢
①因为遍历是从中间遍历的,那么保证了增量最小
②当Ai>Aj时,如果把Ai也改为Aj,那最后的数肯定N还要小。当Ai<Aj时,AiAi明显比AjAj的增量小
这里还要注意的是如果第一对不相等的数的位置在len/2+1的话要分情况修改
如 abbc,abc
当a>c时要修改成abba,这里是因为c处在低位b处在高位,如果该成a(b+1)(b+1)a,增量大小可想而知
当a<c时要修改成a(b+1)(b+1)a,这里是因为a处在高位b处在低位,如果改成cbbc,同理...
下面附上不仅长还不优雅的代码
幼稚园的数学题搞了我几个小时,我真是太辣稽了(感觉是自己在讽刺自己......)
#include<cstdio>
#include<cstring>
char s[50005];
int main()
{
int n;
while(~scanf("%d",&n))
for (int k=1;k<=n;k++)
{
scanf("%s",s);
int top=0,ed=strlen(s)-1,len=strlen(s)-1;
int flag=0;
if (len==0)
{
if (s[0]>='0'&&s[0]<='8') printf("Case %d: %c\n",k,s[0]+1);
else printf("Case %d: 11\n",k);
continue;
}
if (len&1)
{
top=len>>1; ed=top+1;
while(top>=1&&ed<=len-1)
{
if (s[top]==s[ed]) --top,++ed;
else
{
if (top==len>>1)
{
if (s[top]=='0') s[ed]=s[top]='1';
else s[top]=s[ed]=(s[top]<s[ed]?s[top]+1:s[top]);
}
else
{
if (s[top]<s[ed])
{
s[len>>1]=s[(len>>1)+1]=(s[len>>1]+1);
s[ed]=s[top];
}
else
s[ed]=s[top];
}
flag=1;
break;
}
}
while(top>=1&&ed<=len-1)
{
if (s[top]!=s[ed])
s[top]=s[ed]=(s[top]=='0'?'0':s[top]),flag=1;
--top,++ed;
}
if (flag) s[ed]=s[top];
else
{
if (s[top]>s[ed]) s[ed]=s[top];
else
if (s[top]<s[ed])
{
if (top!=len>>1)
++s[len>>1],++s[(len>>1)+1];
else s[top]=s[ed]=(s[top]+1);
}
else
if (s[top]==s[ed])
++s[len>>1],++s[(len>>1)+1];
}
top=len>>1; ed=top+1;
--top,++ed;
while(top>=0&&ed<=len)
{
if (s[top+1]>'9')
{
s[top+1]=s[ed-1]='0';
s[top]=s[ed]=(s[top]+1);
}
--top,++ed;
}
if (s[0]>'9') s[0]='0',s[len]='1',printf("Case %d: 1%s\n",k,s);
else printf("Case %d: %s\n",k,s);
}
else
{
top=ed=len>>1;
--top,++ed;
while(top>=1&&ed<=len-1)
{
if (s[top]==s[ed]) --top,++ed;
else
{
if (s[top]<s[ed]) s[ed]=s[top],++s[len>>1];
else s[ed]=s[top];
flag=1;
break;
}
}
while(top>=1&&ed<=len-1)
{
if (s[top]!=s[ed])
s[top]=s[ed]=(s[top]=='0'?'0':s[top]),flag=1;;
--top,++ed;
}
if (flag) s[ed]=s[top];
else
{
if (s[top]>s[ed]) s[ed]=s[top];
else if (s[top]<s[ed]) s[ed]=s[top],++s[len>>1];
else ++s[len>>1];
}
top=ed=len>>1;
--top,++ed;
while(top>=0&&ed<=len)
{
if (s[top+1]>'9')
{
s[top+1]=s[ed-1]='0';
s[top]=s[ed]=(s[top]+1);
}
--top,++ed;
}
if (s[0]>'9') s[0]='0',s[len]='1',printf("Case %d: 1%s\n",k,s);
else printf("Case %d: %s\n",k,s);
}
}
}