题意
$S(1) = "COFFEE", S(2)="CHICKEN"$,$S(n) = S(n-2)+S(n-1)$,请输出 $S(n)$ 中从第 $k$ 个字符开始的10个字符(若不足10个输出到末尾即可),$1 leq n leq 500, 1 leq k leq min({|S(n)|, 10^{12}})$。
分析
记 $f(i)$ 表示 $S(i)$ 的长度,$f(i) = f(i-2)+f(i-1)$.
递归调用 $solve(n, k)$ 表示 $S(n)$ 的第 $k$ 个字符,
若 $n leq 2$ 直接返回答案,
$n > 2$ 时,若 $k > f(i-2)$,调用 $solve(n-1, k-f(n-2))$;否则调用 $solve(n-2, k)$.
注意特判 $k > f(n)$.
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 510; char s1[10] = "COFFEE"; char s2[10] = "CHICKEN"; ll n, k; ll f[maxn]; void init() { f[1] = 6;f[2] = 7; int i; for(i = 3;i < maxn;i++) { f[i] = f[i-2] + f[i-1]; if(f[i] > 1e12+10) break; } for(int j = i+1;j < maxn;j++) //超过1e12,直接按相等处理,不然会溢出 f[j] = f[i]; } char solve(ll n, ll k) { if(k > f[n]) return 'A'; if(n == 1) return s1[k-1]; if(n == 2) return s2[k-1]; if(k > f[n-2]) return solve(n-1, k-f[n-2]); else return solve(n-2, k); } int main() { init(); int T; scanf("%d", &T); while(T--) { scanf("%lld%lld", &n, &k); for(int i = 0;i < 10;i++) { char ch = solve(n, k+i); if(ch == 'A') break; printf("%c", ch); } printf(" "); } }