POJ 1019 number sequece数学处理

来源:互联网 发布:页面加载完毕后执行js 编辑:程序博客网 时间:2024/06/03 18:05

题意很简单,数列构造如下11212312341234561234567...

给出任意位数n,要求找出第n位是几

第一次做的时候钻牛角尖了,结果wa了好久也不过,后来整理了下思路,发现并不困难

首先我们定义,ai为一个序列,其内容为从1到i所有整数写出所形成的数字序列,例如a6=123456 ,a11=1234567891011,以此类推。

给出一个n,分以下几个步骤得到答案:

①先确定第n位处于的“序列号”,即ai,同时就可以确定这个数字是在序列ai的第几位,这个只需要用n减去前(i-1)个a序列的总长度即可。为此我们要做预处理,生成ai的长度存在数组里,并维护一个前缀和数组,规模35000就足够了,因为题目中最多要求到21亿,35000的规模可以生成26亿数字大概。

②再确定这个数字是属于序列ai中的哪个整数p,由我们的定义,这个整数一定介于[1,i],这个用循环即可实现,复杂度并不高。

③再确定这个数字是整数p的 第几位,道理类似,得到了这个信息就可以求得那个数字了

#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<string>#include<stack>#include<queue>#include<algorithm>#include<cstdlib>//#include<windows.h>#define maxn 201314#define inf 0x3f3f3f3f#define LL long longusing namespace std;int t;int n;LL digit[35010];LL sum_digit[35010];int ppow(int m,int n)//replace for pow function,which will not be compiled in POJ.{    int ans=1;    for(int i=1;i<=n;i++)    {        ans*=m;    }    return ans;}void init()//get the length of every sequence,meanwhile we update a prefix sum .{    memset(digit,0,sizeof(digit));    memset(sum_digit,0,sizeof(sum_digit));    int flag=1;    for(int i=1;i<=35000;i++)    {        int tmp=i;        int d=0;        while(tmp)//for each i ,we get the digits of i        {            tmp/=10;            d++;        }        for(int j=0;j<=(d-2);j++)        {            digit[i]+=(j+1)*9*((int)ppow(10,j));        }        digit[i]+=d*(i-(int)ppow(10,d-1)+1);        sum_digit[i]=sum_digit[i-1]+digit[i];    }}int getdit(int i){    int ans=0;    while(i)    {        i/=10;        ans++;    }    return ans;}int main(){    init();    //cout<<sum_digit[35000]<<endl;    //have successfully get digit for sequence i    cin>>t;    while(t--)    {        cin>>n;        int num=-1;        //step 1        for(int i=1;i<=35000;i++)        {            if(sum_digit[i]>=n&&sum_digit[i-1]<n){                num=i;                break;            }        }        n-=sum_digit[num-1];        //step 1 finished        //now we'll find the nth digit of "sequence num"        //cout<<n<<endl;        int p=0;        int numnum;        int tmp=n;        //cout<<num<<" "<<n<<endl;        //step 2        for(int i=1;i<=num;i++)        {            p+=getdit(i);            if(p>=n)            {                numnum=i;                tmp-=(p-getdit(i));                break;            }        }        //step 2 finished        //cout<<numnum<<endl;        //cout<<tmp<<endl;        //now we'll find the tmp-th digit of the integer numnum.        int ttmp=getdit(numnum);        int ans=-1;        //step 3        for(int i=1;i<=(ttmp+1-tmp);i++)        {            ans=numnum%10;            numnum/=10;        }        //step 3 finished        cout<<ans<<endl;    }}


0 0