CodeVS1280 无限序列

http://codevs.cn/problem/1280/

题意:有一个无限序列:123456789101112……问第Ai位是什么数字。

线性的模拟会超时,因为这里的序列很有规律,所以可以考虑用数学方法来计算。

序列是由每个正整数依次连接的,但是正整数的位数有所不同,无法统一计算,因此应该先观察Ai位对应的正整数是几位的。

可以预先处理好小于某10的幂的所有正整数位数之和t[],以便根据的Ai和t[]大小关系来快速检索相应的位数。

得到位数后,根据Ai和t[]的差整除位数的结果计算出实际数字在当前位数的全部数字中的排名,并得到实际数字。

再根据Ai和t[]的差对位数取模的结果计算出第Ai位是实际数字中的第几位。

最后直接从实际数字中取出该位即可。

代码:

var
  a:array[0..14]of qword;
  t:array[0..15]of qword;
  n,i,j,ii:longint;
  k,x:qword;
begin
  t[0]:=1;
  for i:=1 to 15 do t[i]:=t[i-1]*10;
  a[0]:=0;
  for i:=1 to 14 do a[i]:=a[i-1]+9*t[i-1]*i;
  readln(n);
  for i:=1 to n do
    begin
      readln(k);
      if k<10 then
        begin
          writeln(k);
          break;
        end;
      for j:=14 downto 0 do
        if a[j]<k then break;
      x:=(k-a[j]-1) div (j+1)+t[j];
      for ii:=1 to j-(k-a[j]-1) mod (j+1) do
        x:=x div 10;
      writeln(x mod 10);
    end;
end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值