D - ABC Transform
解法:首先第0层是给定的字符串,然后,第t层可以看做是t个t层的完全二叉树,这样的话,最后一层的最大编号数为n*2^t,最大达到了1e5 * 2^(1e18),一个巨大的数字。但是显然给定的k范围没有这么大,所以要从k下手。
首先如果考虑朴素做法,从树底部往上一步一步走,是O(t)解法,过不了,但是可以通过k来剪枝,当t比较大的时候,k每次找父亲的时候会变成(k+1)/2,最多64次左右变成1,也就是第一个二叉树的最左边一列,容易发现最左边一列是有规律的,假如最左边字母是A,那么最左边一列是ABCABCAB........,此时O(1)地给出结果即可。(代码第11行)
#include <bits/stdc++.h>
using namespace std;
#define debug cout<<"!!!"<<endl;
#define int long long
#define For(i, a, b) for (int i = (a); i <= (b); ++i)
const int N = 1e5+5;
char s[N]; int q,t,k;
char ask(int t,int k){
if(t==0) return s[k]; //已经到第一层了
if(k==1) return 'A'+(s[1]-'A'+t)%3; //到达最左边一列
else return 'A'+(ask(t-1,(k+1)/2)-'A'+(!(k%2)+1))%3; //k为奇数,相对父亲+1,否则相对父亲+2,然后对3取余
}
signed main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin>>(s+1)>>q;
For(i,1,q){
cin>>t>>k;
cout<<ask(t,k)<<'\n';
}
}
E - (∀x∀)
这题不难,可惜赛场上读错题了,害
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define For(i, a, b) for (int i = (a); i <= (b); ++i)
const int N=1e6+5, mod=998244353;
int T,n; char s[N], t[N];
inline void add(int&a,int b){a=(a+b)%mod;}
inline void mul(int&a,int b){a=(a*b)%mod;}
bool check(char* s,char* t){
for(int i=1; i<=n; i++){
if(s[i]>t[i]) return 1;
if(s[i]<t[i]) return 0;
}
return 1;
}
inline void solve(){
int l=1,r=n;
while(l<=r){ //构建最终的目标串T
t[l]=t[r]=s[l];
l++; r--;
}
int mid=l+r>>1, ans=0;
for(int i=1; i<=mid; i++){
mul(ans,26);
add(ans,s[i]-'A'); //当前位取比s[i]小的字母,后面可以任取
}
if(check(s,t)) add(ans,1); //如果s串 >= t串,那么答案额外+1
cout<<ans<<'\n';
}
signed main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin>>T; while(T--){
cin>>n>>(s+1);
solve();
}
}