福州大學第十五屆程式設計競賽 G
阿新 • • 發佈:2019-02-16
Silchen有一個第1代字串"FZU",現在定義一個下一代生成如下
字元'F'可以生成字串"FZU"
字元'Z'可以生成字串"FZ"
字元'U'可以生成字串"FU"
例如:
第1代是"FZU"
第2代是"FZUFZFU"
第3代是"FZUFZFUFZUFZFZUFU"
Silchen想知道第n代的第k個位置的字元是什麼
Input
題目包含多組測試資料,每組測試資料第一行是T表示組數
接下來有T行
每行兩個整數n, k,表示Silchen想知道第n代第k個位置的字元是什麼
0<T<=10 0<n<=100 0<k<=1000000000且保證位置k一定有字元
Output
每組測試資料輸出第n代第k個位置的字元
Sample Input
3
1 1
2 5
3 3
Sample Output
F
Z
字元'F'可以生成字串"FZU"
字元'Z'可以生成字串"FZ"
字元'U'可以生成字串"FU"
例如:
第1代是"FZU"
第2代是"FZUFZFU"
第3代是"FZUFZFUFZUFZFZUFU"
Silchen想知道第n代的第k個位置的字元是什麼
Input
題目包含多組測試資料,每組測試資料第一行是T表示組數
接下來有T行
每行兩個整數n, k,表示Silchen想知道第n代第k個位置的字元是什麼
0<T<=10 0<n<=100 0<k<=1000000000且保證位置k一定有字元
Output
每組測試資料輸出第n代第k個位置的字元
Sample Input
3
1 1
2 5
3 3
Sample Output
F
Z
U
思路:和之前校賽的那個題目類似,但是由於在火車這個題目沒有細看,原來是一道很水的遞迴題目。
直接列舉是不太現實的,會TLE,所以要巧妙的遞迴,由於是父代生子代,所以我們可以計算出每一代字元有多少個,然後通過長度來不斷縮小字元的範圍,最後確定結果,一個細節是當n=24時,字元數量已經為1e9了。
詳情看程式碼
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 1e5 + 5; int f[105], n, k; char solve(int l, int r, int step, int flag) { if(step == n + 1) { if(flag == 1) return 'F'; //第一部分 if(flag == 2) return 'Z'; //第二部分 return 'U'; //第三部分 } if(flag == 1) { int a = f[n-step], b = (r - l + 1 - f[n-step]) / 2;//a為確定第一部分的位置 b為確定第二部分的位置 if(k < l + a) return solve(l, a + l - 1, step + 1, 1); //屬於第一部分的內容 else if(k < l + a + b) return solve(l + a, l + a + b - 1, step + 1, 2);//屬於第二部分的內容 else return solve(l + a + b, r, step + 1, 3);//屬於第三部分的內容 } else { int a = f[n-step], b = r - l + 1 - f[n-step]; if(k < l + a) return solve(l, a + l - 1, step + 1, 1); else return solve(a + l, r, step + 1, flag); } } int main() { f[0] = 1; f[1] = 3; for(int i = 2; i <= 24; i++) f[i] = 2 * f[i-1] + f[i-2];//計算每一層的字元數量 int T; while(scanf("%d", &T) == 1){ while(T--){ scanf("%d%d", &n, &k); if(n > 24) n = 24; char ch = solve(1, f[n], 1, 1); printf("%c\n", ch); } } return 0; }