• UVA 10706 Number Sequence


    UVA_10706

    首先我们可以把这串数中的通项摘出来,就是12345……(n-1)n,这串数就是由这个通项依次拼接而成的。

    意识到上面一点后,我们不妨把原序列的第i位转化成是哪一通项中的哪一位,这样我们不就好处理多了么。要能够实现这样的转化,我们需要知道两组数据,第一,每个通项中有多少个数字,第二,根据第一组数据算出从第一项开始至第n项一共有多数字。这样我们就可以算出第i位是在第n+1项中的i-sum[n]项,其中sum[]代表的就是第二组数据。在算这两组数据的时候我们采用递推的方式去计算,而且我们只要把最大的情况算出来并保留中间结果即可(也即打表),这样就避免了重复计算。

    下面的问题就是最大情况是什么样的情况了,我们不妨用高斯公式算一下,就算通项每项只增加一个数字,那么最大项的标号也不会超过sqrt(imax)+1,何况有时还不只增加一个数字。

    但是由于实际上的最大项的长度要大一些,所以我们打表的时候也要把数组开大一些。

    #include<stdio.h>
    #include<string.h>
    #include<ctype.h>
    #include<math.h>
    #define MAX 2147483647
    int K;
    long long int sum[100000];
    char b[1000000];
    int pan(int x)
    {
    int n=0;
    while(x)
    {
    x/=10;
    n++;
    }
    return n;
    }
    void init()
    {
    int i,j,a;
    K=sqrt(MAX)+1;
    j=1;
    for(i=1;i<=K;i++)
    {
    sprintf(&b[j],"%d",i);
    while(isdigit(b[j]))
    j++;
    }
    a=sum[0]=0;
    for(i=1;i<=K;i++)
    {
    a+=pan(i);
    sum[i]=sum[i-1];
    sum[i]+=a;
    }
    }
    int main()
    {
    int i,j,k,n,num,t,min,mid,max;
    init();
    scanf("%d",&t);
    while(t--)
    {
    scanf("%d",&num);
    min=0;
    max=K;
    while(1)
    {
    mid=(min+max)/2;
    if(mid==min)
    break;
    if(sum[mid]>=num)
    max=mid;
    else
    min=mid;
    }
    k=num-sum[mid];
    printf("%c\n",b[k]);
    }
    return 0;
    }


  • 相关阅读:
    linux 系统运维工具13款
    Django2.0 分页的应用
    jvm优化
    SSH-key 在Windows下如何生成公钥和私钥
    申请Let’s Encrypt免费证书,给自己网站增加https访问
    wordpress上传主题以及安装插件 出现ftp的问题解决方案
    php压缩文件
    linux下 如何切换到root用户
    TP3.2.3框架隐藏Home模块以及index.php入口文件的方法
    PHP打开错误提示和关闭错误提示的方法
  • 原文地址:https://www.cnblogs.com/staginner/p/2192949.html
Copyright © 2020-2023  润新知