Problem A. Googol String
Small input 7 points |
|
Large input 12 points |
|
Problem
A "0/1 string" is a string in which every character is either 0
or 1
. There are two operations that can be performed on a 0/1 string:
- switch: Every
0
becomes1
and every1
becomes0
. For example, "100" becomes "011". - reverse: The string is reversed. For example, "100" becomes "001".
Consider this infinite sequence of 0/1 strings:
S0 = ""
S1 = "0"
S2 = "001"
S3 = "0010011"
S4 = "001001100011011"
...
SN = SN-1 + "0" + switch(reverse(SN-1)).
You need to figure out the Kth character of Sgoogol, where googol = 10100.
Input
The first line of the input gives the number of test cases, T. Each of the next T lines contains a number K.
Output
For each test case, output one line containing "Case #x: y", where x is the test case number (starting from 1) and y is the Kth character of Sgoogol.
Limits
1 ≤ T ≤ 100.
Small dataset
1 ≤ K ≤ 105.
Large dataset
1 ≤ K ≤ 1018.
Sample
switch是让字符串中0变1,1变0得到新串。100 变为 011
reverse是将字符串首尾对调,比如1000 变为0001
问n=10^100时 Sn的第K个字符是0还是1。
思路:10的100次方很大,其实不必求出来Sn 因为k的范围很小。而不论第k个是哪个字符,都是从S1的0变过来的。而且10的100次方的前缀都是前面的S1~Sn-1组成的。
长度是个什么关系呢?
S1 = 1 ,Sn = Sn-1 * 2 + 1
从递推式:
Sn = Sn-1 + '0' + switch(reverse(Sn-1)可以知道0的位置,一定是0。这句话好奇怪。。。。
0的位置都是这些数1 2 4 8 16,这些是2的0~4次方,所以如果位置是2的整数次方,一定是0
如果不是呢?找到第一个小于k的2的整数次方位置,超出对称点位置的对称位置进行一次01变换就是答案。那么统计下变换了几次,可以依据最终的2的整数次方时的数值得到答案。
变化一次跟变化3次的结果是一样的,变化偶数次的结果跟最初答案是一样的,用异或运算处理就可以了,一次没有就是0,加一就通过与1异或实现,最终结果再跟0异或,其实这一步不用的,最终是几就是答案。
python代码如下
import sys
sys.stdin = open('in.txt', 'r')
sys.stdout = open('output.txt', 'w')
T = input()
case = 1
while case <= T:
k = input()
mid = 0
i = k;
i >>= 1
while i: #这组循环统计整数二进制形式下最开头的1是多少位
mid += 1
i >>= 1
ans = 0
mid = 1<<mid; #得到最初k的对称中心位置
while k != 1 and mid != k:
if mid > k: #不是小于k的中心点就找更小的中心点
mid >>= 1
continue
k -= mid
k = mid - k #得到对称位置
ans ^= 1
mid >>= 1
print 'Case #%d: %d' % (case, ans)
case += 1
复杂度logN 10^18方也可以秒过。