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;
}