The only difference between the easy and the hard versions is the maximum value of \(k\).

You are given an infinite sequence of form "112123123412345…" which consist of blocks of all consecutive positive integers written one after another. The first block consists of all numbers from \(1\) to \(1\), the second one — from \(1\) to \(2\), the third one — from \(1\) to \(3\), …, the i-th block consists of all numbers from \(1\) to \(i\).

So the first \(56\) elements of the sequence are "11212312341234512345612345671234567812345678912345678910". Elements of the sequence are numbered from one. For example, the \(1\)-st element of the sequence is \(1\), the \(3\)-rd element of the sequence is \(2\), the \(20\)-th element of the sequence is \(5\), the \(38\)-th element is \(2\), the 56-th element of the sequence is \(0\).

Your task is to answer \(q\) independent queries. In the i-th query you are given one integer ki. Calculate the digit at the position ki of the sequence.

有一个无限长的数字序列,其组成为1 1 2 1 2 3 1.......1 2 ... n...,即重复的1 ~ 1,1 ~ 2....1 ~ n,这个数列连起来成为一个串,每位数字算一个元素,求第k(k<=1e18)个元素是什么

输入格式

The first line of the input contains one integer \(q(1≤q≤500)\) — the number of queries.

The i-th of the following q lines contains one integer \(k_i (1≤k_i≤10^{18})\) — the description of the corresponding query.

输出格式

Print q lines. In the i-th line print one digit \(x_i (0≤xi≤9)\) — the answer to the query i, i.e. xi should be equal to the element at the position ki of the sequence.

样例输入1

5
1
3
20
38
56

样例输出1

1
2
5
2
0

样例输入2

4
2132
506
999999999999999999
1000000000000000000

样例输出2

8
2
4
1

题解

首先把原数列变成这样:

1
12
123
1234
12345
123456
1234567
12345678
123456789
12345678910
1234567891011
123456789101112
12345678910111213
1234567891011121314

你会发现,这个形状抽象以下就是这样:

当然每一块实际上不是等高的,这个斜边斜率之所以会改变,是因为其最后一个数字位数不同,在第一块,每一行增加一位,第二组每一行增加2位...

我们只需要事先预处理出每块含数字的数量,然后拿到\(k\)以后,进行二分就能找到\(k\)在哪一块.

那么怎么预处理呢?

首先已知:

  1. 第一块第一行是1个数字

  2. 第一块每行增加\(1\)个,第二块每行增加\(2\)个,第三行每行增加\(3\)个,第\(i\)块每行增加\(i\)个,设为\(d_i\)

  3. 第一块有\(9\)行,第二块有\(90\)行,第三块有\(900\)行,第\(i\)块有\(9 \times 10^{i-1}\),设为\(l_i\)

那就可以用等差数列求和公式预处理

注意,每一块都有自己的通项公式,描述该块内第几行有多少数字

那么现在求每一块内数字数量的问题就变成了 已知首项和公差,求前\(n\)项和.

首项由前一块的通项公式得出,公差为\(d_i\), 由\(n=l_i\)可以求出该块数字数量,保存下来.

找到在哪一块之后,\(k\)减去前面所有块的数字数量,然后二分找到哪一行,每一行的数量由该块通项公式得出.

找到在哪一行之后,进行和以上类似的操作

比如这一行是

1
12
123
1234
12345
123456
1234567
12345678
123456789
12345678910
1234567891011
123456789101112

是不是似曾相识?

又是这个图,还是分块,分成1位数,2位数,3位数若干块(若干公差不同的等差数列),找到\(k\)在哪一块,然后枚举即可.

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 10;
long long a[15], b[15], c[15], T, n;
int main() {
for (int i = 1; i <= N; i++) {
long long x = i, l = 1, r = 0;
while (x--) l *= 10, r = r * 10 + 9;
l /= 10;
a[i] = (r - l + 1) * i;
b[i] = b[i - 1] + a[i];
c[i] = c[i - 1] + (b[i - 1] + i + b[i]) * (r - l + 1) / 2;
}
scanf("%lld", &T);
while (T--) {
scanf("%lld", &n);
long long pos = lower_bound(c + 1, c + N + 1, n) - c, l = 1, r = 0,
x = pos, t;
n -= c[pos - 1];
t = b[pos - 1];
while (x--) l *= 10, r = 10 * r + 9;
l /= 10;
long long L = l;
while (l <= r) {
int mid = (l + r) >> 1, cnt = mid - L + 1;
if ((2 * t + pos + cnt * pos) * cnt / 2 >= n)
r = mid - 1;
else
l = mid + 1;
}
long long cnt = l - L;
n -= (2 * t + pos + cnt * pos) * cnt / 2;
pos = lower_bound(b + 1, b + N + 1, n) - b;
n -= b[pos - 1];
long long ans = 1;
for (long long i = 1; i < pos; i++) ans *= 10;
t = (n - 1) / pos;
n -= t * pos;
ans += t;
n = pos - n;
while (n--) ans /= 10;
printf("%lld\n", ans % 10);
}
return 0;
}

Numerical Sequence (Hard vision) 题解的更多相关文章

  1. cf1216E2 Numerical Sequence (hard version)(思维)

    cf1216E2 Numerical Sequence (hard version) 题目大意 一个无限长的数字序列,其组成为\(1 1 2 1 2 3 1.......1 2 ... n...\), ...

  2. Numerical Sequence (easy version)

    http://codeforces.com/problemset/problem/1216/E1 E1. Numerical Sequence (easy version) time limit pe ...

  3. [CF1216E] Numerical Sequence hard version

    题目 The only difference between the easy and the hard versions is the maximum value of k. You are giv ...

  4. cf1216E2 Numerical Sequence (hard version) 二分查找、思维题

    题目描述 The only difference between the easy and the hard versions is the maximum value of k. You are g ...

  5. CF1216E Numerical Sequence

    题目链接 问题分析 奇奇怪怪的题... 首先思路达成一致,从大到小一步一步确定位置. 我们一边分析,一边讲算法. 1121231234123451234561234567123456781234567 ...

  6. [CF1177B]Digits Sequence (Hard Edition)题解

    一个简单的模拟,首先先计算当前是几位数,然后根据几位数推断当前的数是什么,然后求出该位即可 #include <cstdio> int main(){ long long k; scanf ...

  7. Numerical Sequence(hard version),两次二分

    题目: 题意: 已知一个序列: 112123123412345123456123456712345678123456789123456789101234567891011... 求这个序列第k个数是多 ...

  8. 【二分】CF Round #587 (Div. 3)E2 Numerical Sequence (hard version)

    题目大意 有一个无限长的数字序列,其组成为1 1 2 1 2 3 1.......1 2 ... n...,即重复的1~1,1~2....1~n,给你一个\(k\),求第\(k(k<=10^{1 ...

  9. CF1177A Digits Sequence (Easy Edition) 题解

    Content 一个序列由从 \(1\) 开始的数字不断在末端拼接,就像这样:\(12345678910111213141516...\).现在,给定一个数字 \(k\),请输出这个序列的第 \(k\ ...

随机推荐

  1. [原创][开源] SunnyUI.Net 系列文章目录

    SunnyUI.Net, 基于 C# .Net WinForm 开源控件库.工具类库.扩展类库.多页面开发框架 Blog: https://www.cnblogs.com/yhuse Gitee: h ...

  2. Spring之多数据源切换的应用

    这不是一个新的知识点扩展,顶多算是,Spring的AOP特性的一个应用.那么下面开始今天的学习之旅! 场景 数据库读写分离,或者分库,总之多数据源的场景,怎么样实现自动切换(PS:不考虑各种分库分表的 ...

  3. [ARC060D] 最良表現

    题目   点这里看题目. 分析   由于 KMP 的失配数组有着天然的找循环节的功能,因此我们不难想到对原串进行两次 KMP ,一正一反.   可以发现如下的规律:   1. 原串无循环节,这个时候 ...

  4. Random Point in Triangle【随机数解决期望值问题】

    Random Point in Triangle 题目链接(点击) 题目描述 Bobo has a triangle ABC with A(x1,y1),B(x2,y2)A(x1,y1),B(x2,y ...

  5. deepin文件用途

    Bin:二进制文件, 存放二进制文件Dev:存放外接设备,其中外接设备不能被直接使用需要挂载(启动设备)Etc:存放配置文件Home:家目录,出了root用户外的其他用户类似于Windows中的use ...

  6. vulstack红队评估(三)

    一.环境搭建: ①根据作者公开的靶机信息整理 没有虚拟机密码,纯黑盒测试...一共是5台机器,目标是拿下域控获取flag文件   ②虚拟机网卡设置 centos双网卡模拟内外网: 外网:192.168 ...

  7. vue 生成二维码+截图

    链接生成二维码 1.npm安装 npm install --save qrcodejs2 2.引入 import QRCode from 'qrcodejs2' 3.生成二维码 new QRCode( ...

  8. 团队进行Alpha冲刺--项目测试

    这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 团队作业第五次--Alpha冲刺 这个作业的目标 团队进行Alpha冲刺--项目测试 作业正文 如下 其他参 ...

  9. 「从零单排canal 03」 canal源码分析大纲

    在前面两篇中,我们从基本概念理解了canal是一个什么项目,能应用于什么场景,然后通过一个demo体验,有了基本的体感和认识. 从这一篇开始,我们将从源码入手,深入学习canal的实现方式.了解can ...

  10. 新老单点的改造——-理解Cookie、Session、Token

    近期参与了新老单点的改造,一直想总结一下,发现这篇文章比较贴切. 整理了如下: 随着交互式Web应用的兴起,像在线购物网站,需要登录的网站等等,马上就面临一个问题,那就是要管理会话,必须记住哪些人登录 ...