二分查找——UVa 10706 - Number Sequence

来源:互联网 发布:没有网络怎么重装系统 编辑:程序博客网 时间:2024/06/05 14:39

思路:

要得到给定位置的数字,只需要知道该位置处在的序列Sk和距离Sk首位的偏移量即可。

设seqLen[k]表示:S1S2…Sk的总长度,对于给定的i,用二分查找确定所在的Sk, i-Sk-1就是偏移量。

/*Sk的长度:k的范围[1  , 9  ]: k[10 , 99 ]: 9 + (k-9)*2[100, 999]: 9 + 90*2 + (k-99)*3...*/#include <iostream>#include <cstdio>#include <string>using namespace std;#define MAXN 31270#define MAXLEN 146000unsigned int seqLen[MAXN];void InitSequenceLength(void){seqLen[0] = 0;unsigned int delta = 1, c = 10, sum = 0;int i;for (i = 1; seqLen[i-1] <= 2147483647; i++){//当i为10、100、1000...时,delta需要加1if (i == c){delta++;c *= 10;}sum += delta;seqLen[i] = seqLen[i-1] + sum;}}int BSearch(int low, int high, unsigned int targ){while (low <= high){int mid = (low + high) / 2;if (targ == seqLen[mid]){return seqLen[mid-1];}else if (targ < seqLen[mid]){high = mid - 1;}else{low = mid + 1;}}return seqLen[high];}int main(void){InitSequenceLength();string maxSeq;maxSeq.reserve(MAXLEN+10);int i;for (i = 1; maxSeq.length() < MAXLEN; i++){char temp[10];sprintf(temp, "%d", i);maxSeq += temp;}int ncases;scanf("%d", &ncases);while (ncases-- != 0){unsigned int p;scanf("%d", &p);int i = BSearch(1, 31268, p);printf("%c\n", maxSeq[p-i-1]);}return 0;}