題目描述
有一個數列,滿足兩個性質:
1.數列中任意兩端相鄰且長度相等的部分不完全相同,比如3 6 3 6 是不合法的。
2.該數列是左右滿足條件1的數列中字典序最小的。給出一個整數N,求數列的第N項。
輸入
一個整數N
N<=
輸出
一個數,表示數列的第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 |
可以看到模數是,而這個就是答案,那我們怎麼求?
將表格統一一下:
% =
由此可以得出:
( ) ( ) 1 ( ))
所以,我們只需要一直除以二,直到 時,我們就可以輸出它除以二的次數(及)
代碼
#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;
}
}
}