【华为OD机试 2023】 对称美学(C++ Java JavaScript Python)

题目描述

对称就是最大的美学,现有一道关于对称字符串的美学。已知:

  • 第1个字符串:R
  • 第2个字符串:BR
  • 第3个字符串:RBBR
  • 第4个字符串:BRRBRBBR
  • 第5个字符串:RBBRBRRBBRRBRBBR

相信你已经发现规律了,没错!就是第 i 个字符串 = 第 i - 1 号字符串取反 + 第 i - 1 号字符串;

取反(R->B, B->R);

现在告诉你n和k,让你求得第n个字符串的第k个字符是多少。(k的编号从0开始)

输入描述

第一行输入一个T,表示有T组用例;

解析来输入T行,每行输入两个数字,表示n,k

  • 1 ≤ T ≤ 100;
  • 1 ≤ n ≤ 64;
  • 0 ≤ k < 2^(n-1);

输出描述

输出T行表示答案;

输出 “blue” 表示字符是B;

输出 “red” 表示字符是R。

备注:输出字符串区分大小写,请注意输出小写字符串,不带双引号。

用例

输入5
1 0
2 1
3 2
4 6
5 8
输出red
red
blue
blue
blue
说明第 1 个字符串:R -> 第 0 个字符为R
第 2 个字符串:BR -> 第 1 个字符为R
第 3 个字符串:RBBR -> 第 2 个字符为B
第 4 个字符串:BRRBRBBR -> 第 6 个字符为B
第 5 个字符串:RBBRBRRBBRRBRBBR -> 第 8 个字符为B
输入1
64 73709551616
输出red
说明

题目解析

看不懂题目?没关系。我们先把题目中的字符串画出来。根据题目红色的是R.蓝色的是B

image-20230307133934938

仔细观察表格你会看到:

第5个字符串的后半部分,和第4个字符串完全相同;

第4个字符串的后半部分,和第3个字符串完全相同;

第3个字符串的后半部分,和第2个字符串完全相同;

第2个字符串的后半部分,和第1个字符串完全相同;

当前字符串与前一个字符串存在依赖关系,明显跟递归有关系了啊!

在仔细观察,你会发现每个字符串的前半部分,与前一个字符串的颜色正好相反。

C++


#include<iostream>
#include<vector>
using namespace std;

// 递归函数,找到第n个字符串的第k个字符
char find(long n, long k) {
    // 第1个字符串
    if (n == 1) {
        return 'R';
    }
    // 第2个字符串
    if (n == 2) {
        if (k == 0) return 'B'; // 如果k为0,则返回B
        else return 'R'; // 否则返回R
    }
 
    long len = 1L << (n-2); // 计算字符串长度
    // 如果 k 在后半段,则与前一个字符串相同
    if (k >= len) {
        long pos = k - len; // 计算在前一个字符串中的位置
        return find(n - 1, pos); // 递归求解前一个字符串中的字符
    } else {
        // 如果 k 在前半段,则与前一个字符串相反
        return find(n - 1, k) == 'R' ? 'B' : 'R'; // 递归求解前一个字符串中的字符,并根据结果返回相反的字符
    }
}
 
 
int main()
{
    int t;
    cin >> t;
    vector<vector<long>> input_case;
    // 读入所有测试用例
    for (int i=0;i<t;i++) {
        long n, k;
        cin >> n >> k;
        vector<long> single_case = {n, k};
        input_case.push_back(single_case);
    }
 
    // 对每个测试用例进行求解
    for (int i = 0; i < t; i++) {
        long n = input_case[i][0];
        long k = input_case[i][1];
        string res = find(n, k) == 'R' ? "red" : "blue"; // 根据求解结果判断是红色还是蓝色
        cout << res << endl; // 输出结果
    }
    
    return 0;
}

JavaScript

const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

// 递归函数,找到第n个字符串的第k个字符
function find(n, k) {
  // 第1个字符串
  if (n === 1) {
    return 'R';
  }
  // 第2个字符串
  if (n === 2) {
    if (k === 0) return 'B'; // 如果k为0,则返回B
    else return 'R'; // 否则返回R
  }

  const len = 1 << (n-2); // 计算字符串长度
  // 如果 k 在后半段,则与前一个字符串相同
  if (k >= len) {
    const pos = k - len; // 计算在前一个字符串中的位置
    return find(n - 1, pos); // 递归求解前一个字符串中的字符
  } else {
    // 如果 k 在前半段,则与前一个字符串相反
    return find(n - 1, k) === 'R' ? 'B' : 'R'; // 递归求解前一个字符串中的字符,并根据结果返回相反的字符
  }
}

let t;
const input_case = [];

rl.on('line', (line) => {
  if (!t) {
    t = parseInt(line);
  } else {
    const [n, k] = line.split(' ').map(Number);
    input_case.push([n, k]);
    if (input_case.length === t) {
      // 对每个测试用例进行求解
      for (let i = 0; i < t; i++) {
        const [n, k] = input_case[i];
        const res = find(n, k) === 'R' ? 'red' : 'blue'; // 根据求解结果判断是红色还是蓝色
        console.log(res); // 输出结果
      }
      rl.close();
    }
  }
});

Java

import java.util.*;

public class Main {
    // 递归函数,找到第n个字符串的第k个字符
    public static char find(long n, long k) {
        // 第1个字符串
        if (n == 1) {
            return 'R';
        }
        // 第2个字符串
        if (n == 2) {
            if (k == 0) return 'B'; // 如果k为0,则返回B
            else return 'R'; // 否则返回R
        }

        long len = 1L << (n-2); // 计算字符串长度
        // 如果 k 在后半段,则与前一个字符串相同
        if (k >= len) {
            long pos = k - len; // 计算在前一个字符串中的位置
            return find(n - 1, pos); // 递归求解前一个字符串中的字符
        } else {
            // 如果 k 在前半段,则与前一个字符串相反
            return find(n - 1, k) == 'R' ? 'B' : 'R'; // 递归求解前一个字符串中的字符,并根据结果返回相反的字符
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        List<List<Long>> input_case = new ArrayList<>();
        // 读入所有测试用例
        for (int i = 0; i < t; i++) {
            long n = sc.nextLong();
            long k = sc.nextLong();
            List<Long> single_case = new ArrayList<>();
            single_case.add(n);
            single_case.add(k);
            input_case.add(single_case);
        }

        // 对每个测试用例进行求解
        for (int i = 0; i < t; i++) {
            long n = input_case.get(i).get(0);
            long k = input_case.get(i).get(1);
            String res = find(n, k) == 'R' ? "red" : "blue"; // 根据求解结果判断是红色还是蓝色
            System.out.println(res); // 输出结果
        }
    }
}

Python

def find(n, k):
    if n == 1:
        return 'R'
    if n == 2:
        if k == 0:
            return 'B'
        else:
            return 'R'
    len = 1 << (n-2)
    if k >= len:
        pos = k - len
        return find(n-1, pos)
    else:
        return 'B' if find(n-1, k) == 'R' else 'R'

t = int(input())
input_case = []
for i in range(t):
    n, k = map(int, input().split())
    single_case = [n, k]
    input_case.append(single_case)
for i in range(t):
    n = input_case[i][0]
    k = input_case[i][1]
    res = 'red' if find(n, k) == 'R' else 'blue'
    print(res)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值