2019牛客暑期多校训练营(第十场)Coffee Chicken——递归

题意

$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("\n");
    }
}

猜你喜欢

转载自www.cnblogs.com/lfri/p/11372365.html