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;
    }
}
posted @ 2023-03-07 13:12  Keith-  阅读(66)  评论(0)    收藏  举报