ABC242 D (找规律

本文讲解了一种通过将字母构成的二叉树结构,解决查询第ttt层第kkk个节点的问题。当t大于60时,采用循环节技巧;否则,根据节点位置计算初始字母。核心在于递归模拟树的构造并找到根节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

D - ABC Transform
思路:
把原序列的每一个字母当成成一个根,可以发现这是一棵 t t t 层的二叉树
题目意思是查询第 t t t 层的第 k k k 个节点
这样一棵二叉树第 t t t 层有 2 t 2^t 2t 个节点
显然如果 t > 60 t>60 t>60,节点数目是非常多的,算一下 2 60 2^{60} 260 肯定大于 1 0 8 10^8 108,这样第 k k k 个节点就一定是从初始序列的第一个字母开始变化的,当 t t t 始终大于 60 60 60 时,每次向下延申肯定选择最左边的节点,这样就会有循环节,我们模拟一下初始字母对应的循环节,然后就 % 3 \%3 %3 就可以得到 t = 60 t=60 t=60 的时候的字母,即作为递归求解时的根节点
如果 t < = 60 t<=60 t<=60,所查询的节点它就可能不是从初始序列的第一个字母开始变化
应该是从初始序列第 ⌊ k 2 t ⌋ \lfloor \frac{k}{2^t} \rfloor 2tk 个开始变化
这样我们确定出来根节点了
然后递归模拟拓展的过程求答案就好了
code:

#include<bits/stdc++.h>
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define mem(x, d) memset(x, d, sizeof(x))
#define eps 1e-6
using namespace std;
const int maxn = 2e6 + 9;
const int mod = 998244353;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
map <char, string> ma, mb;
char ans;

void dfs(int t, char x){
	if(t == 0){
		ans = x;return;
	}
	m %= (1ll << t);
	if(m < (1ll << (t - 1))){
		dfs(t - 1, mb[x][0]);
	}
	else dfs(t - 1, mb[x][1]);
}
void work()
{
	ma['A'] = "ABC";ma['B'] = "BCA";ma['C'] = "CAB";
	mb['A'] = "BC";mb['B'] = "CA";mb['C'] = "AB";
	string s;cin >> s;
	int q;cin >> q;
	while(q--){
		cin >> n >> m;
		--m;
		char x;
		if(n > 60){
			x = ma[s[0]][(n-60)%3];
		}
		else x = s[m/(1ll<<n)];
		n = min(n, 60ll);
		dfs(n, x);
		cout << ans << endl;
	}
}

int main()
{
	ios::sync_with_stdio(0);
//	int TT;cin>>TT;while(TT--)
	work();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值