题意:S(1)="COFFEE",S(2)="CHICKEN" ,S(n) = S(n−2)+S(n−1),请输出 S(n) 中从第 k 个字符开始的10个字符(若不足10个输出到末尾即可),(1≤n≤500,1≤k≤min(|S(n)|,1012)
思路:那会好多人过了这题,就尝试去写了一下,然而我处理的是区间,答案输出是对的,但是莫名其妙的段错误,可能用区间处理递归太多了吧,后来看到xjl学姐过了,她用for循环模拟的递归,是对十个位置上每个字符进行处理,仔细想想,这样写的确比我的要好,太弱了,连递归都写不好~T_T 以下来自官方题解
记 f(i) 表示 S(i) 的长度,f(i) = f(i−2) + f(i−1).
递归调用 solve(n,k) 表示 S(n) 的第 k 个字符,
若 n≤2 直接返回答案,
n>2 时,若 k>f(i−2),调用 solve(n−1,k−f(n−2))否则调用 solve(n−2,k).
注意特判 k>f(n).
Code
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll t, n, k; ll f[58] = {0,6,7}; char s1[10] = "COFFEE", s2[10] = "CHICKEN"; void dfs(int n, ll k){ if(k>f[n]) return; if(n==1) printf("%c", s1[k-1]); else if(n==2) printf("%c", s2[k-1]); else { if(k>f[n-2]) dfs(n-1,k-f[n-2]); else dfs(n-2,k); } } int main() { for(int i=3;i<=57;i++) f[i]=f[i-1]+f[i-2]; //for (int i = 1; i <= 57; i++) printf("%lld ", f[i]); scanf("%d",&t); while(t--){ scanf("%d%lld", &n, &k); if(n>57) if(n&1) for(int i=0;i<10;i++) dfs(57,k+i); else for(int i=0;i<10;i++) dfs(56,k+i); else for(int i=0;i<10;i++) dfs(n,k+i); printf("\n"); } return 0; }
至于为什么这里n只用计算到57,仔细看题目就知道k最大只能到1e12,因此n大到一定程度后,后面查找的其实还是用的前面的S(57)或者S(56),自己把f[i]打个表就知道了