[c++]數列

題目描述

有一個數列,滿足兩個性質:

1.數列中任意兩端相鄰且長度相等的部分不完全相同,比如3 6 3 6 是不合法的。

2.該數列是左右滿足條件1的數列中字典序最小的。給出一個整數N,求數列的第N項。

輸入

一個整數N
N<=10100010^{1000}
輸出
一個數,表示數列的第N項。

樣例輸入

20

樣例輸出

3

淺析

找規律

顯然這是一道找規律的題
因爲要求字典序最小,所以可以知道第一個數一定是 “1”
那第二個數就只能是“2”了噻,關鍵來了,第三個數怎麼求呢?
取”3“?那有沒有字典序更小的部分可以取呢?其實,這個時候我們知道題目是要“相鄰的並且長度相同的部分不相同”,這便是突破口,則此時我們又可以重新回到起點,再取一個“1”,當然第四個數,我們就可以取“3”了(如果繼續取2,則有” 1 2 1 2“,顯然”1 2“ = “1 2”)
繼續推下去,可以發現:(這太難推了吧)
這個數列實際上是這樣的:

1 2 1 3 1 2 1 4 1 2 1 3 1 2 1 5 1 2 1 3 1 2 1 4 1 2 1 3 1 2 1 6

這個數列,就是將前面一部分“copy”下來,然後把最後一個數加“1”即可
(具體證明,留給大佬思考,其實就是本蒟蒻不會罷了)

答案求解

先看“1”,每隔一個數,便會出現一次,所以,如果 n % 2 = 1 便可輸出“1”。
再來分析“2”,除第一個“2”外,剩下的便是隔三個位置出現一次,那我們可以將每四個看爲一組,如果 n % 4 = 1 ,我們即可輸出 2
……
然後來個小總結
其實可以發現:
我們設這個數列爲{ans}

n % 2 = 1 ans = 1
n % 4 = 2 ans = 2
n % 8 = 4 ans = 3
n % 16 = 8 ans = 4
n % 32 = 16 ans = 5
n % 64 = 32 ans = 6

可以看到模數是2x2^x,而這個xx就是答案,那我們怎麼求xx
將表格統一一下:
nn % 2x2^x = 2x12^{x - 1}
由此可以得出:
nn \equiv 2x2^x (modmod 2x2^x)\Longrightarrow (nn // 2x2^x) \equiv 1 (modmod 2x2^x))
所以,我們只需要一直除以二,直到 n=1n = 1 時,我們就可以輸出它除以二的次數(及xx

代碼

#include<cstdio>
#include<cstring>
#define M 1000
#define reg register

char C[M + 5];
int A[M + 5],lenc,ans;

int main(){
    gets(C);
    lenc = strlen(C);
    for (reg int i = 0;i < lenc; ++ i)
        A[i + 1] = C[i] - '0';
    while(1){
        ++ ans;
        if (A[lenc] % 2){
            printf("%d\n",ans);
            return 0;
        }
        int x = 0;
        for (reg int i = 1;i <= lenc; ++ i){
            A[i] += x * 10;
            x = A[i] % 2;
            A[i] /= 2;
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章