T4 咕咕东的奇妙序列

题目

时间限制

1s

空间限制

64MB

题目描述

咕咕东 正在上可怕的复变函数,但对于稳拿A Plus的 咕咕东 来说,她早已不再听课。

此时她在睡梦中突然想到了一个奇怪的无限序列:112123123412345…

这个序列由连续正整数组成的若干部分构成,其中第一部分包含1至1之间的所有数字,第二部分包含1至2之间的所有数字,第三部分包含1至3之间的所有数字,第i部分总是包含1至i之间的所有数字。

所以,这个序列的前56项会是11212312341234512345612345671234567812345678912345678910,其中第1项是1,第3项是2,第20项是5,第38项是2,第56项是0。

咕咕东 现在想知道第 k 项数字是多少!但是她睡醒之后发现老师讲的东西已经听不懂了,因此她把这个任务交给了你。

输入格式

输入由多行组成。

第一行一个整数q表示有q组询问(1<=q<=500)

接下来第i+1行表示第i个输入ki,表示询问第ki项数字。(1<=ki<=1018)

输出格式

输出包含q行

第i行输出对询问ki的输出结果。

样例输入

5
1
3
20
38
56

样例输出

1
2
5
2
0

数据点

在这里插入图片描述

做法

1、sum[x]表示数列中第一次出现x的位置,a[x]表示从1~x所占位数。
2、对于每个输入的位置k,用二分法找第一个sum[mid]>=k的mid,mid即为k所在的前项和。
3、令k=k-weizhi(mid-1,0),求出第一个a[mid]>k的mid即为k所在的数字。
4、令k=k-weizhi(mid-1,1),k为所在数字的级数,将该数字mid转化为字符串,求出第k位即为所求的输出数字。
5、在求位置的函数中,将求sum和求a合在一起进行,因为求sum需要a作为上一级的数列长度来求解。
6、先不断求出到pow数量级的sum和a,当x在该数量级中,再求出从该数量级最小值到x的sum和a

错误

1、注意在两次查找时,均找的是第一个使返回结果>k的值,所以当weizhi(mid,0/1)>=k时,应使mid=r-1而非r+1
2、一开始考虑将前项和全部求出储存在数组中,发现会出现RE的错误,考虑应该是数组越界的原因,因为数据范围为1e18,所以不考虑将其存到一个大数组中(但是感觉应该可以存到按数量级递增的一个数组中)。
3、to_string 是c++11支持的,在低版本中不支持

代码

#include<iostream>
#include<string>
#include<cmath>
#include<cstdio>
using namespace std;
long long weizhi(long long x,int ch)
{
    
    
 long long pow=1,sum=0,a=0,n=0,weishu=0;
 while(true)
 {
    
    
  pow=pow*10;
  weishu=weishu+1;
  if(x>pow-1)
  {
    
    
   n=pow-pow/10;
   sum=sum+a*n+(n+1)*n/2*weishu;
   a=a+n*weishu;
  }
  else
  {
    
    
   n=x-pow/10+1;
   sum=sum+a*n+(n+1)*n/2*weishu;
   a=a+n*weishu;
   break;
  }
 }
 if(ch==0)
  return sum;
 else
  return a;
}
int main()
{
    
    
 long long ans,k;
 long long q,l,r,mid;
 cin>>q;
 for(int i=0;i<q;i++)
 {
    
    
  cin>>k;
  l=0;r=1e9;
  while(l<=r)
  {
    
    
   mid=(l+r)>>1;
   if(weizhi(mid,0)>=k)
   {
    
    
    ans=mid;
    r=mid-1;
   }
   else
    l=mid+1;
  }
  k=k-weizhi(ans-1,0);
  l=0;
  r=ans+1;
  while(l<=r)
  {
    
    
   mid=(l+r)>>1;
   if(weizhi(mid,1)>=k)
   {
    
    
    
    ans=mid;
    r=mid-1;
   }
   else
    l=mid+1;
  }
  k=k-weizhi(ans-1,1);
  string s =to_string(ans);
  printf("%d\n",s[k-1]-'0');  
  } 
 return 0;
 } 

猜你喜欢

转载自blog.csdn.net/alicemh/article/details/105389027
T4