poj 1019 Number Sequence

二分, 数学

用分段的思想解决

定义3个数组

len[i]表示i这个数字有多少位,len[1-9] = 1,因为个位数只有1为,len[10-99] = 2,有两位………………

num[i]表示1到i,一共占了几位,num[9]=9,因为123456789,num[10] = 11, 12345678910

sum[i] = num[1]+num[2]…………num[i]

sum[4] = 10 , 因为1121231234

所以对于一个位置n,用分段的思想,不断缩小范围

先找到sum[m] <= n && n < sum[m+1]

然后求出差值  delta = n - sum[m]

然后再在num中查找,num[k] <= delta && delta < num[k+1]

那么最后就能确定到一个数字上

再求差值  __delta = delta - num[k]

表示的是k+1的第__delta个数字是什么

 

位置最大是2147483647,打表能发现,sum[]数组只要计算到30000多就可以了,所以len,num,sum数组都计算到3万多

对于位置的查找   sum[m] <= n && n < sum[m+1]   ,    num[k] <= delta && delta < num[k+1]

可以顺序查找,因为数据并不大,但是我写了二分查找

最后运行了0ms

 

#include <iostream>

#include <cstdio>

#include <cstring>

using namespace std;

const int N = 31500;

const int LIM = 2147483647;

int len[N+100],num[N+100];

long long sum[N+100];



void Init()

{

    for(int i=1; i<=9; i++)        len[i] = 1;

    for(int i=10; i<=99; i++)    len[i] = 2;

    for(int i=100; i<=999; i++) len[i] = 3;

    for(int i=1000; i<=9999; i++) len[i] = 4;

    for(int i=10000; i<=N+10; i++) len[i] = 5;

    num[1] = sum[1] = 1;

    for(int i=2; i<=N; i++){

        num[i] = num[i-1] + len[i];

        sum[i] = sum[i-1] + num[i];

    }

//    for(int i=1 ;i<=10 ;i++)

//        cout << len[i] << "    " << num[i] << "     " << sum[i] << endl;

}



int binsum(int key){

    //sum[m] <= key && sum[m+1] > key

    int low = 1 , high = N;

    while(low <= high){

        int mid = (low + high) >> 1;

        if(sum[mid] == key)        return mid;

        else if(key < sum[mid]) high = mid - 1;

        else                    low = mid + 1;

    }

    if(sum[low] <= key) return low;

    else return high;

}



int binnum(int key){

    //num[m] <= key && num[m+1] > key

    int low = 1 , high = N;

    while(low <= high){

        int mid = (low + high) >> 1;

        if(num[mid] == key) return mid;

        else if(key < num[mid]) high = mid - 1;

        else                    low = mid + 1;

    }

    if(num[low] <= key) return low;

    else                return high;

}



void fun(int m){

    cout << m%10 << endl;

}



void __fun(int m ,int delta){

    int k = binnum(delta);

//    cout << k << "  " << num[k] << "        " << num[k+1] << endl;

    if(delta == num[k]) fun(k);

    else{

        int __delta = delta - num[k];

        int stack[10],top=0;

        int tmp = k+1;

        while(tmp){

            stack[++top] = tmp%10; tmp /= 10;

        }

        for(int i=1,j=top; i<=j; i++,j--)

            swap(stack[i],stack[j]);

        cout << stack[__delta] << endl;

    }

}



int main(){

    Init();

    int cas,n;

    cin >> cas;

    while(cas--){

        cin >> n;

        int m = binsum(n);

        int delta = n - sum[m];

        if(delta == 0) fun(m);

        else           __fun(m,delta);

        n++;

    }

    return 0;

}

 

 

你可能感兴趣的:(sequence)