题目链接
http://codeforces.com/contest/1144/problem/E
题意
给你一个长度为n的两个字符串s和t ,只包含小写字母,并且s的字典序小于t,
存在一些字典序在不小于s并且不大于t的字符串,找到这些字符串按字典序排序后最中间的那一个输出。题目保证字典序在s和t之间的字符串有奇数个。
比如 s= "az" ,t= "bf"
s和t之间的字符串有 ["az", "ba", "bb", "bc", "bd", "be", "bf"].,最中间的字符串为bc。
字符串长度小于2*10^5;
题解
如果给你两个整数x,y, 那么中值是(x+y)/2;
字符串同理。
因为每个字母都对应一个ASCII码,每个字符都可以看成一个数字。字符串就可以看成是一个26进制的数字字符串。
先把每个字符串的每个字符减去‘a’,然后这些字符的值就在0-25之间了。
然后把两个字符串看成26进制数字。这两个26进制数字加起来除以2
最后这个26进制数字每一位都在加上‘a’,变成a到z的字符,然后输出。
26进制加法和除法原理上和10进制加法除法相同,想不通的话先写两个10进制的数字字符串模拟一下试试
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
int n;
char s[maxn],t[maxn];
char ans[maxn]; // ans=c+s
char ans2[maxn]; // ans2=ans/2
int main(){
scanf("%d",&n);
scanf("%s",s);
scanf("%s",t);
int cnt=0; //存储进位
for(int i=n-1;i>=0;i--){ // 模拟26进制加法
s[i]-='a';
t[i]-='a';
ans[i]=(s[i]+t[i]+cnt)%26;
cnt=(s[i]+t[i]+cnt)/26;
}
//加完之后最高位可能有进位,进位存储在cnt变量
//模拟26进制除法,除以2
for(int i=0;i<n;i++){
ans2[i]=(ans[i]+cnt*26)/2;
cnt=ans[i]%2;
}
//把26进制数加上字符‘a'输出
for(int i=0;i<n;i++){
printf("%c",ans2[i]+'a');
}
return 0;
}