Time Limit: 1000 MS Memory Limit: 32768 KB
Description
有一个十六进制序列由S1S2…Sk组成,其中Sk由1到k的十六进制数字依次组成。给定一个位置i,返回第i个位置上的字符。
例如,S1S2…Sk的前200个字符为
112123123412345123456123456712345678123456789123456789A123456789AB123456789ABC123456789ABCD123456789ABCDE123456789ABCDEF123456789ABCDEF10123456789ABCDEF1011123456789ABCDEF101112123456789ABCDEF10111213
所以i=3时,字符为2,i=192时,字符为F。
Input
有多组输入数据,每行包含一个位置i,1<=i<=2000000000。
Output
对于每个给定的位置i,输出该位置上的字符,对于A~F字符,请输出大写字母。
Sample Input
3
192
Sample Output
2
F
要看懂序列的规律,每次每段序列中都加了一个16进制数,这一数字是上一数字加一得到的。实际上最大的问题在于如何确认n在哪一段序列中,下面的代码中我在动态更新s的同时,也在对n进行减操作,实际上就是为了确认n在哪一段序列中,如果n减到小于等于0了,说明n就在当前的s中。
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<cstdio>
using namespace std;
string s;
char mi[20];
int main()
{
// cout<<s.max_size()<<endl;//用来查看string的最大长度,是4开头的19位数
int n;
while(cin>>n)
{
s="0";
for(int i=1;;++i)
{
itoa(i,mi,16);//把当前的数变成16进制存在mi字符数组中
strupr(mi);//由于用函数转过来的字母是小写,用这个函数变成大写
s+=mi;//将mi接在s后面
n-=s.size()-1;//这步实际上是在确认n在哪一段序列中
if(n<=0)//如果n<=0说明n就在当前的序列中
{
n+=s.size()-1;//让n恢复为减之前的n
break;
}
}
cout<<s[n]<<endl;//直接用n做下标访问s即可
}
return 0;
}