Constraints
Time Limit: 1 secs, Memory Limit: 32 MB
Description
半人马座(Centaurus)不仅有着美丽的传说,其中的比邻星还是距离太阳系最近的恒星。C博士是一直热衷于对地外文明的探测,最近他发现了一组来自半人马座的奇怪电波信号:1 1 3 1 5 3 7 1……,她怀疑这是来自那里的遥远文明对地球的问候。经过她和助手们的努力,终于发现这是一个很有规律的频率信号a1,a2,a3,……。其中a1=1,a3=3这是信号的开始标志,其余时刻的频率有如下关系:
a2n = an
a4n+1 = 2*a2n+1 - an
a4n+3 = 3*a2n+1 - 2*an
(n>=1)
信号可能很长,其中会有一些分隔标志。C博士在研究中发现这些分隔标志其实是很容易就可以判别出来的,因为它就满足an = n。
为了更进一步发掘这一长串信号的含义,C博士需要知道a1,a2,……,aL中分隔标志有多少个。
Input
只有一个整数L(1<=L<232),表示所要分析信号的长度。
Output
输出一个整数,为这段长L的信号中分隔标志的个数。
解题思路:参考了网上牛人找出的规律是:a(x) 的值等于x的二进制的倒序所对应的十进制数。那么这道题就转化为在L范围内找出二进制是回文数的个数。
按照这个思路,我首先自己写了一个代码,对于从1到L的数,逐个对其进行二进制回文,再判断该回文值是否等于该值,从而进行统计,但是最终超时了。
参考了网上其他人的算法,代码如下:
#include <iostream>
#include <cstdio>
using namespace std;
int countEvenBits(int num, long long L){ // 偶数位回文串
long long a = num;
while (num) {
a = (a<<1) | (num & 1);
num >>= 1;
}
return (a && a <= L ? 1:0 );
}
int countOddBits(int num, long long L){ // 奇数位回文串
long long a = num;
long long b = num;
int c = 0,count = 0;
while (num) {
c = (c << 1) | (num &1);
num >>= 1;
count ++ ;
}
a = (a<< (count +1)) | c; // 以0为中心
b = (((b << 1) | 1) << count ) | c; // 以1为中心
return (a && a <= L? 1:0) + (b && b <= L ? 1: 0);
}
int main(){
long long L;
cin >> L;
long long result = 0;
for (int i = 0; i <= L && i <(1<<16) ; i++) {
result += countEvenBits(i,L);
if (i<(1<<15)) {
result += countOddBits(i, L);
}
}
cout << result << endl;
}
以上的代码解释:只需要对一半的数进行回文串,然后统计个数。比如说对于1这个数,进行偶数回文串统计的话就是11,进行奇数回文就是101或者111,只要11,101,111在L范围内,就进行统计。
比较他人做法与自己做法,终于明白为啥自己的做法会超时了,这是因为我对每一个不管是不是所需要的数都进行求回文串的操作,这必然会超时。而新的做法就是只对符合要求的回文串进行回文串操作。因为每个符合要求的数都是由回文串组成,每一个回文串都是能够由一半的数组成。