【MX-X19-T5】「FeOI Round 4.5」天使のクローバー 解题报告
分析
感觉不如 T4 难
看到这种输入很少的题目就要先考虑模拟一下。令 \(T_i\) 为转换 \(i\) 次得到的序列。
\[\begin{aligned}
T_0&=01\\
T_1&=0111\\
T_2&=0111000111\\
T_3&=0111000111010111000111\\
\end{aligned}
\]
对,我相信你已经观察到了 \(T_3=T_2+T_0+T_2\)(加法表示字符串拼接)。
然后由 \(T_i\) 的定义有 \(T_i=T_{i-1}+T_{i-3}+T_{i-1}\)。
然后你就可以像平衡树上查找排名对应值一样的访问到 \(r\) 对应的值了。
判断是否有解只需要看变换后长度是否够长即可(你不需要真的跑 \(10^{18}\) 次,跑到长度为 \(10^{18}\) 就行了)。
代码
const int N=1e7+100;
int T,tot,a[20]={0,1,1,1,0,0,0,1,1,1};
ll len[N],x,r,k=1;
void solve(){
scanf("%lld%lld",&x,&r);
++r;
if(x<=tot && r>len[x]){printf("-1\n");return;}
int nw=tot;
while(nw>2){
if(r<=len[nw-1]) --nw;
else{
r-=len[nw-1];
if(r<=len[nw-3]) nw=nw-3;
else{
r-=len[nw-3];
--nw;
}
}
}
--r;
printf("%d\n",a[r]);
}
int main()
{
#if !ONLINE_JUDGE
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
#endif
len[0]=2,len[1]=4,len[2]=10,tot=2;
while(len[tot]<=1e18){
++tot;
len[tot]=len[tot-1]+len[tot-3]+len[tot-1];
if(tot>=60) break;
}
T=read();
while(T--) solve();
return 0;
}