Googol String

Problem A. Googol String

This contest is open for practice. You can try every problem as many times as you like, though we won't keep track of which problems you solve. Read the Quick-Start Guide to get started.
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 becomes 1 and every 1 becomes 0. 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


Input 
 

Output 
 
4
1
2
3
10

Case #1: 0
Case #2: 0
Case #3: 1
Case #4: 0


    谷歌的校招题,题意是:字符串S0是空串,Sn = Sn-1 + '0' + switch(reverse(Sn-1)

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方也可以秒过。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值