zoukankan      html  css  js  c++  java
  • codeforces 1216E1 Numerical Sequence (easy version) (前缀和/二分)

    题目链接:https://vjudge.net/problem/CodeForces-1216E1

      题目描述就是给你一串数,可以分成若干段,每段为这个数字以及这个数字前几个数就像1 12 123 1234 12345这样,然后给你一个数i

    让你求这个数列第ai位的数。

      首先我们先想对于1234567891011121314这列数来说,每个数字的末位处于这个数以及这个数前面所有数的位数之和,比如5就位于第

    5个位置,10的0位于第11个位置,14的4位于第19个位置,我们可以用一个前缀和来表示这些数的位置。

      然后对于112123123412345这列数来说, 第一个1出现的位置就是1第一个2的位置就是1的位数加上12的位数,第一个11末位1的位置

    就是1 + 12 + 123 + 1234 。。。的位数,即上面位数前缀和的前缀和。

      对于一个位置num来说,它前面必定有若干个1 12 123 1234这样的序列,所以我们就可以用二分在前缀和的前缀和序列中找一个小于他

    的最大的数,那么他们的差就是序列12345678910...列数中的某个位置,即在前缀和序列中的位置,这里我们可以再用一次二分,然后求得

    一个大于或者等于这个数的最小的值,那么num在减去这个位置就是答案了

      

    #include<set>
    #include<map>
    #include<stack>
    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<cctype>
    #include<string>
    #include<vector>
    #include<climits>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define endl '\n'
    #define max(a, b) (a > b ? a : b)
    #define min(a, b) (a < b ? a : b)
    #define mst(a) memset(a, 0, sizeof(a))
    #define IOS ios::sync_with_stdio(false)
    #define _test printf("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n")
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> P;
    const double pi = acos(-1.0);
    const double eps = 1e-7;
    const ll MOD = 1e9+7;
    const int INF = 0x3f3f3f3f;
    const int _NAN = -0x3f3f3f3f;
    const int NIL = -1;
    const int maxn = 2e5+10;
    ll _ls[maxn], _sumls[maxn];
    int main(void) {
        for (ll i = 1; i<maxn; ++i) {
            ll t = (ll)((log10(i)+eps)+1); //求数字位数
            _ls[i] = _ls[i-1] + t; //求1234567位数的前缀和(1234567中每个数字末位对应的位数)
            _sumls[i] = _sumls[i-1] + _ls[i]; //求前缀和的前缀和(1121231234中每个数字第一次出现时其末位对应的位数)
        }
        //printf("%lld %lld\n", _ls[maxn-1],_sumls[maxn-1]);
        int n;
        scanf("%d", &n);
        while(n--) {
            ll num;
            scanf("%lld", &num);
            ll *pos1 = lower_bound(_sumls+1, _sumls+maxn, num); 
            if (*pos1 == num) 
                printf("%d\n", (pos1-_sumls)%10);//刚好对应某个第一次出现的数字的末尾
                //指针相减默认是int类型,如果用lld输出结果会出错
            else {
                //对应某个数字的某位上
                --pos1; 
                num -= *pos1;
                ll *pos2 = lower_bound(_ls+1, _ls+maxn, num);
                string nums; //把这个数字转成字符串
                ll t2 = pos2-_ls;
                while(t2) {
                    nums += t2%10 + '0';
                    t2 /= 10;
                }
                reverse(nums.begin(), nums.end());
                --pos2;
                num -= *pos2; //求出结果在字符串上的位置
                printf("%c\n", nums[num-1]);
                nums.clear();
            }
        }
        return 0;
    }
  • 相关阅读:
    Python增删改查文件
    Python实现验证用户信息后跳转网页的功能
    Python文件操作
    python集合操作
    字典的用法
    二分查找
    git命令记录
    JavaScript高级程序设计window对象学习记录
    JS模块化简介(读书笔记)
    Webpack代码分割 + 懒加载
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/12288504.html
Copyright © 2011-2022 走看看