Googol字符串【Google Kickstart2015 Round A Problem A】
Googol字符串
“0/1字符串”是一个字符串,其中每个字符都是 0或 1。
有两个操作可以在 0/1字符串上执行:
switch:把 1都变为 0,0都变为 1。例如,100 变为 011。
reverse:字符串反转。 例如,100 变为 001。
考虑这个 0/1 字符串的无限序列:
S0=“”
S1=“0”
S2=“001”
S3=“0010011”
S4=“001001100011011”
…
SN=SN−1+“0”+switch(reverse(SN−1))
请你求出Sgoogol中的第K个字符,其中googol=10100。
输入格式
第一行包含整数 T,表示共有 T组测试数据。
每组数据占一行,包含一个整数 K。
输出格式
每组数据输出一个结果,每个结果占一行。
结果表示为 Case #x: y,其中 x
是组别编号(从 1
开始),y
是 Sgoogol
中的第 K
个字符。
数据范围
1≤T≤100
,
1≤K≤10^18
输入样例:
4
1
2
3
10
输出样例:
Case #1: 0
Case #2: 0
Case #3: 1
Case #4: 0
思路
\[S_1 = '0'
\]
\[S'_1 = '1'
\]
\[S_2 = S_1 + '0' + S'_1 = 001
\]
\[S'_2 = S_1 + '1' + S'_1 = 011
\]
\[S_3 = S_2 + '0' + S'_2 = S_1 + '0' + S'_1 + '0' + S_1 + '1' + S'_1 = 0010010
\]
\[S'_3 = S_2 + '1' + S'_2 = S_1 + '0' + S'_1 + '1' + S_1 + '1' + S'_1 = 0011011
\]
通过把玩前三项,容易得到通式\(S_n = S_{n-1} + '0' + S'_{n-1}\)和\(S'_n = S_{n-1} + '1' + S'_{n-1}\)
\[L_n = 2L_{n-1} + 1
\]
\[\frac{L_n + 1}{L_{n-1} + 1} = 2
\]
因此,长度通式$L_n = 2^n - 1 $
\[k \le 2^n -1
\]
\[n \ge log_2(k+1)
\]
\[n = \left \lceil log_2(k+1) \right \rceil
\]
因此,第k个数在\(S_{\left \lceil log_2(k+1) \right \rceil}\)内
然后比较判断k在三部分中哪一部分递归处理就好啦(
注意标记一下是\(S_{n-1}\)还是\(S'_{n-1}\)
代码
点击查看代码
#include<iostream>
#include<cmath>
typedef long long LL;
const char nl = '\n';
using namespace std;
int get(LL n,LL k,int type){
LL t = (1ll << (n - 1)) - 1;
if(k == (t + 1))return type;
else if(k <= t)return get(n - 1,k,0);
else return get(n - 1,k - t - 1,1);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int T;
cin >> T;
for(int i = 1; i <= T; i ++ ){
LL k;
cin >> k;
cout << "Case #" << i << ": " << get(ceil(log2(k+1)),k,0) << nl;
}
}

浙公网安备 33010602011771号