2019牛客暑期多校训练营(第十场)B-Coffee Chicken

>传送门<

题意: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;
}
View Code

至于为什么这里n只用计算到57,仔细看题目就知道k最大只能到1e12,因此n大到一定程度后,后面查找的其实还是用的前面的S(57)或者S(56),自己把f[i]打个表就知道了

猜你喜欢

转载自www.cnblogs.com/wizarderror/p/11369218.html