这道题目有点麻烦,首先用二分法找到第i个位置在Si的哪一个里面,所以要生成长度的辅助数组arr和length,用动态规划的方法生成是很简单的,因为输入的i有限,可以测试出来Si最多到31268项,算出来i是哪个si里面的第多少个位置(就是程序里面func函数算出来的i)就容易了,首先在初始化的时候初始化字符数组S1S2S3.......S31268,在里面取a[i]打印出来就行了。
#include <stdio.h>
#include <string.h>
#define MAX_LENGTH 31300
long long arr[MAX_LENGTH+1];
long long length[MAX_LENGTH+1];
char a[MAX_LENGTH*5];
void init_length()
{
int i, start;
char buf[10];
arr[1] = 1;
a[1] = '1';
start = 2;
for(i=2; i<MAX_LENGTH; i++)
{
sprintf(buf, "%d", i);
memcpy(a+start, buf, strlen(buf));
start += strlen(buf);
if(i>=1 && i<=9)
{
arr[i] = arr[i-1] + 1;
continue;
}
if(i>=10 && i<=99)
{
arr[i] = arr[i-1] + 2;
continue;
}
if(i>=100 && i<=999)
{
arr[i] = arr[i-1] + 3;
continue;
}
if(i>=1000 && i<=9999)
{
arr[i] = arr[i-1] + 4;
continue;
}
if(i>=10000 && i<=99999)
{
arr[i] = arr[i-1] + 5;
continue;
}
if(i>=100000 && i<=999999)
{
arr[i] = arr[i-1] + 6;
continue;
}
}
length[0] = 0;
length[1] = arr[1];
for(i=2; i<=MAX_LENGTH; i++)
{
length[i] = length[i-1] + arr[i];
if(length[i] > 2147483647)
break;
}
//printf("max i=%d value=%I64d\n", i, length[i]);
}
void func(long long index)
{
int l, r, m;
long long i;
l = 0;
r = 31268;
while(1)
{
m = (l+r)/2;
if(index>length[m-1] && index<=length[m])
break;
else if(index > length[m])
l = m+1;
else
r = m-1;
}
i = index - length[m-1];
printf("%c\n",a[i]);
}
int main(void)
{
long long index;
int n, i;
//freopen("input.dat", "r", stdin);
init_length();
scanf("%d", &n);
for(i=1; i<=n; i++)
{
scanf("%I64d", &index);
func(index);
}
return 0;
}