您的位置:首页 > 产品设计 > UI/UE

POJ 1019 number sequece数学处理

2015-12-09 18:52 489 查看
题意很简单,数列构造如下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 long

using 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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: