[CF1216E] Numerical Sequence hard version
题目
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.
Input
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 ki (1≤ki≤1018) — the description of the corresponding query.
Output
Print q lines. In the i-th line print one digit xi (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.
Examples
Input
5
1
3
20
38
56
Output
1
2
5
2
0
Input
4
2132
506
999999999999999999
1000000000000000000
Output
8
2
4
1
Note
Answers on queries from the first example are described in the problem statement.
分析
我们维护一个前缀和数组,然后去找第n个数字在哪一行,然后减去前边几行的数字数目和就是答案。
比如n=5,发现它在第三行,前两行的和为3,5−3=2所以第五个数是2。 但如果n很大的话,比如这题,就会T掉,首先上述思想是可以肯定的,所以要用更高效的办法 首先是找到在第几行。 一行行枚举效率太低,要用到一个分块的思想,按照末位数字的位数分块,这样在每个块里找,枚举每个块的时间复杂度是一个常数,先找到它在哪一块,然后再利用二分的思想确定所在行,因为这个是具有单调性的,那么怎么找呢? 考虑每一块中有多少个数,用变量last记录前几个块的数字和,len记录当前枚举的位数,根据等差数列的求和公式(a1+an)∗n/2,当前块的第一行的数字和是last+len手摸一下就能得出,最后一行是last+len∗cnt,其中cnt就是该块内一共有多少数字,如果n大于前几块的数字和sum,就直接减去,否则就找到了所在块,然后再二分求出是那一行就行,求的方法就是不断更新l和r判断sum与n的关系,找到后再减去前边几行的和就是第n个数字在这一行第几个。 这时候我们再重复一下上述过程,只不过不是拆分行而是拆分每个数(不是数字),比如12345678910,拆成1 2 3 4 5 6 7 8 9 10,1和0不分开的这种。然后再枚举每个数字的位数,依次减去,从而求出第n个数字所在数的位数,最后再把这个数还原出来取它的那个位数就行。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int inf = 0x7f7f7f7f;
const int maxn = ;
int K,M,S,T;
int v[maxn],cnt,map[maxn][maxn],used[maxn];
int ans[maxn][maxn],dis[maxn][maxn],tmp[maxn][maxn];
void floyd(int c[][maxn],int a[][maxn],int b[maxn][maxn]){
int i,j,k;
for(k=;k<cnt;k++){
for(i=;i<cnt;i++){
for(j=;j<cnt;j++){
if(c[v[i]][v[j]]>a[v[i]][v[k]]+b[v[k]][v[j]])
c[v[i]][v[j]]=a[v[i]][v[k]]+b[v[k]][v[j]];
}
}
}
}
void copy(int a[][maxn],int b[][maxn]){
int i,j;
for(i=;i<cnt;i++){
for(j=;j<cnt;j++){
a[v[i]][v[j]]=b[v[i]][v[j]];
b[v[i]][v[j]]=inf;
}
}
}
void solve(int k){
while(k){
if(k%){
floyd(dis,ans,map);
copy(ans,dis);
}
floyd(tmp,map,map);
copy(map,tmp);
k=k/;
}
}
int main(){
int i,j;
int x,y,val;
while(scanf("%d%d%d%d",&K,&M,&S,&T)==){
for(i=;i<=;i++){
for(j=;j<=;j++){
map[i][j]=inf;
ans[i][j]=inf;
tmp[i][j]=inf;
dis[i][j]=inf;
}
ans[i][i]=;
}
memset(used,,sizeof(used));
cnt=;
for(i=;i<M;i++){
scanf("%d%d%d",&val,&x,&y);
if(map[x][y]>val){
map[x][y]=val;
map[y][x]=map[x][y];
}
if(!used[x]){
used[x]=;
v[cnt++]=x;
}
if(!used[y]){
used[y]=;
v[cnt++]=y;
}
}
solve(K);
printf("%d\n",ans[S][T]);
}
return ;
}
[CF1216E] Numerical Sequence hard version的更多相关文章
- Numerical Sequence (easy version)
http://codeforces.com/problemset/problem/1216/E1 E1. Numerical Sequence (easy version) time limit pe ...
- cf1216E2 Numerical Sequence (hard version)(思维)
cf1216E2 Numerical Sequence (hard version) 题目大意 一个无限长的数字序列,其组成为\(1 1 2 1 2 3 1.......1 2 ... n...\), ...
- cf1216E2 Numerical Sequence (hard version) 二分查找、思维题
题目描述 The only difference between the easy and the hard versions is the maximum value of k. You are g ...
- CF1216E Numerical Sequence
题目链接 问题分析 奇奇怪怪的题... 首先思路达成一致,从大到小一步一步确定位置. 我们一边分析,一边讲算法. 1121231234123451234561234567123456781234567 ...
- 【二分】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 ...
- Numerical Sequence(hard version),两次二分
题目: 题意: 已知一个序列: 112123123412345123456123456712345678123456789123456789101234567891011... 求这个序列第k个数是多 ...
- Numerical Sequence (Hard vision) 题解
The only difference between the easy and the hard versions is the maximum value of \(k\). You are gi ...
- CF1264D2 Beautiful Bracket Sequence (hard version)
考虑\(D1\)的\(O(n^2)\),我们直接进行组合处理. 考虑在\(p\)这个位置,左边有\(l\)个(,右边有\(r\)个),左边有\(l\)个问号,右边有\(r\)个问号. 这个位置的贡献为 ...
- CF1264D1 Beautiful Bracket Sequence (easy version)
考虑在一个确定的括号序列中,我们可以枚举中间位置,按左右最长延伸出去的答案计算. 我们很自然的思考,我们直接维护左右两边,在删除一些字符后能够延伸的最长长度. 我们设\(f_{i,j}\)为\(i\) ...
随机推荐
- 【JSP】el、jstl、MVC、三层架构
JSP[Java Server Pages] [概念] java服务器页面 简化的servlet设计 html语法中扩展java 跨平台 JSP全名为Java Server Pages,中文名叫jav ...
- Java实现 LeetCode 762 二进制表示中质数个计算置位(位运算+JDK的方法)
762. 二进制表示中质数个计算置位 给定两个整数 L 和 R ,找到闭区间 [L, R] 范围内,计算置位位数为质数的整数个数. (注意,计算置位代表二进制表示中1的个数.例如 21 的二进制表示 ...
- Java实现 LeetCode 741 摘樱桃(DFS || 递推 || 传纸条)
741. 摘樱桃 一个N x N的网格(grid) 代表了一块樱桃地,每个格子由以下三种数字的一种来表示: 0 表示这个格子是空的,所以你可以穿过它. 1 表示这个格子里装着一个樱桃,你可以摘到樱桃然 ...
- Linux 日志轮替
日志轮替包括两个方面的内容:切割日志文件,轮换日志文件 日志文件的命令规则 如果配置文件中有dateext参数,那么日志文件的后缀会是日期,例如:yum.log-20200424,这样,文件名不会重叠 ...
- 基于Nginx实现访问控制、连接限制
0 前言 Nginx自带的模块支持对并发请求数进行限制, 还有对请求来源进行限制.可以用来防止DDOS攻击.阅读本文须知道nginx的配置文件结构和语法. 1. 默认配置语法 nginx.conf作为 ...
- 详解SpringBoot(2.3)应用制作Docker镜像(官方方案)
关于<SpringBoot-2.3容器化技术>系列 <SpringBoot-2.3容器化技术>系列,旨在和大家一起学习实践2.3版本带来的最新容器化技术,让咱们的Java应用更 ...
- vj提交时常见问题
- Spark Streaming + Kafka Integration Guide原文翻译及解析
前面写了关于kafka和spark streaming的结合使用(https://www.cnblogs.com/qfxydtk/p/11662591.html),其具体使用用法其实来自于原文:htt ...
- @hdu - 6607@ Easy Math Problem
目录 @description@ @solution@ @accepted code@ @details@ @description@ 求: \[\sum_{i=1}^{n}\sum_{j=1}^{n ...
- 动手造轮子:实现一个简单的 AOP 框架
动手造轮子:实现一个简单的 AOP 框架 Intro 最近实现了一个 AOP 框架 -- FluentAspects,API 基本稳定了,写篇文章分享一下这个 AOP 框架的设计. 整体设计 概览 I ...