zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    IDA断点和搜索
    shell grep正则匹配汉字
    吐槽一下jsoup
    mysql函数
    hutools之批量更新
    Hutools之http工具类
    Java通过腾讯邮箱发送邮件
    访问网络资源的方式--application/json和x-www-form-urlencoded
    HttpClient获取数据
    URLConnection类的使用
  • 原文地址:https://www.cnblogs.com/scau20110726/p/3120814.html
Copyright © 2011-2022 走看看