USACO习题:Palindromic Squares

这道题的核心是考回文数字的判断。判断回文的手法基本可以分两类。

1.转换成字符串来判断,也是参考答案里的做法。(思路比较简单,这里不在熬述)

2.数学方式来判断(只能判断数字),使用mod的方法。这个方法的好处是,不要把数字转换成相应进制的表达方式然后再判断。

手法比较巧妙。

 

下面我来讲解下方法2.

首先我们从最简单的十进制讲起,比如有个数 123。

十进制的表示: 1*10^2 + 2*10 + 3

如何把这个数颠倒?

0*10 + 123 % 10 = 3  然后 123/10=12

3*10 + 12%10  = 32 然后 12/10 = 1

32*10 + 1%10 = 321

看出什么规律来了么?

 

我们再来看一下某个回文数字:12321,显而易见12321的颠倒任然是12321。

所以我们得出结论一个数字是回文当且仅当他的颠倒和原数字相等。

 

刚才的例子里,我们是以10进制为例子的,现在我们想想2进制的情况。

我们如何转换10进制到2进制?

12 % 2 = 0 , 12/2=6

6%2     = 0 , 6/2 = 3

3%2     = 1,  3/2 = 1

1%2     = 1

12转换好以后就是1100。发现什么了么?其实10转2产生的字符正是12的2进制数的颠倒,也就是说

使用和刚才10进制相同的方式,一样可以得到2进制的颠倒的值,然后用颠倒和原值比较即可。

或许有人会说:原来的值是10进制的,转成二进制的颠倒比较不会不一样么?

其实这里是比较绕的,无论是10进制还是2进制,他们的值本身是一样的。

也就是说用  二进制颠倒过来的数值 = 原10进制 --> 2进制 --> 颠倒 --> 利用二进制求出该数的值

换句话说不管什么进制怎么转换,其值是不变的,也就是说10进制和2进制的的比较是合理的。

 

回文判断代码
bool is_palindrome(int num,int base){
int reversed = 0,temp=num;
while(temp!=0){
reversed = reversed*base + temp%base;
temp/=base;
}
return (reversed==num);
}

 

如果不了解的话,多调试下代码,体会下吧。

你可能感兴趣的:(USACO)