今天主要学习了无限递归序列(recursive recurrence)的倒推
Secret Cow Code (USACO 2017 Jan, Silver)
给一个string s,F(s)为s加上s的最后一个字符rotate到最左边直到最后一个字符,例如:s=COW, F(s)=COWWCO, F(F(s))=COWWCOOCOWWC
这个操作会无限循环下去,现在给予一个index,求这个index的字符是什么
遇到无限长度的题目求有限的值,考虑倒推 - 从无限推有限 (分开看,思考新的string和旧的string的关系)
首先s的长度每次乘以2,我们可以把s分开看,左边的 s_old 和右边的 s_new, 稍微观察就可以发现 s_new 的字符位置可以 减 (m/2)+1 得到 s_old 的位置 (m 现在s的大小,s_old+s_new, 并且m 是 1-index based)
总结:
无限长度(操作)题目
倒推 - 从无限推有限 (分开看,思考 ”新的“ 和 “旧的” 的关系)
---------------------------------------------------------------------------------------------------------------------------------
C. Mark and His Unfinished Essay
利用倒推的思想,把string s分成 s_old 和 s_new, 然后 求出 s_old 中 对应 s_new 的下标
#include <iostream>
#define int long long
using namespace std;
/*
1
7 3 3
creamii
2 3
3 4
2 9
9
11
12
*/
void solve(){
int n, c, q;
cin>>n>>c>>q;
string s; cin>>s;
int lp[45], rp[45];
lp[0]=1, rp[0]=s.length();
pair<int, int> C[45];
for(int i=1;i<=c;i++){
int l, r; cin>>l>>r;
lp[i]=rp[i-1]+1;
rp[i]=lp[i]+(r-l);
C[i]={l, r};
}
// for(int i=1;i<=c;i++){
// cout<<lp[i]<<" "<<rp[i]<<endl;
// }
for(int i=0;i<q;i++){
int pos; cin>>pos;
for(int j=c;j>=1;j--){
if(pos>=lp[j]&&pos<=rp[j]){
pos = C[j].second-(rp[j]-pos);
}
}
cout<<s[pos-1]<<endl;
}
}
signed main(){
int t; cin>>t;
while(t--){
solve();
}
}