题目:

    

    

    

    

题意:

  已知一个序列:

    112123123412345123456123456712345678123456789123456789101234567891011。。。

  求这个序列第k个数是多少。

分析:

  首先,我们先来看这样一个问题,让求123456789101112131415。。。一直到n的长度是多少,我们会怎么求呢?显然,我们会分开求:1-9一组,10-99一组,100-999一组。。。当然组数不会很多,然后组内其实就是一些位数相等的数的位数的和,那么当然用乘法解决,数清项数就好了,显然第i组的项数(即有几个位数为此组位数的数)是P(i)-P(i-1)(P(a)表示10的a次方),然后每一个数的长度就是i,当然注意一下最后一组的特殊处理。

  求得这个之后有什么用呢?我们可以用它来求什么,我们这样想:其实原序列就是由我们刚求出来的序列组成的,那么是不是我们可以直接根据上面的求法把1到s相加求得以1-s结尾的序列的长度,显然,并不能,这个数字出奇的大,是多少呢?一会儿会用到,一会儿再说,我们先考虑怎么简化运算,显然,可以和上面的处理一样,我们分开处理,1-9,10-99。。。这些怎么处理呢?一会发现,这些其实是一些等差数列,如:1-9是公差为1的等差数列,10-99是公差为二的等差数列,而首项就是我们之前可以求的1-P(i-1)的和这样的话就可以直接带公式求等差数列和了,还有就是边界,处理了最大的就好了。

  现在我们可以求着个序列到哪里是多大了,但是给我们的是长度啊,那就要二分了,二分之后我们便确定了这个序列是在1234。。。到几的一个序列里,是这个的第几位呢?减取前面的就能求出来了,但是知到了是第几位并不能很快的求出是多少,但是没有关系,再次二分,可以确定最后他比1-x多多少,然后就找到x+1的第多出来的哪一位(从高向低数)就好了,这个的复杂度还是比较有保证的:最多也超不过20*20*40*500(有些数字稍微记大了一些),然后就是二分的左右边界,这个只能去试了,算一下多少超了10的18次方还没爆long long就好了。

  好的那么我们再想这样一个问题(别急着看代码):现在我们给你这样的一堆数:

  1

  112

  112123

  1121231234

  112123123412345

  112123123412345123456

  。。。

求第k个数字,这样其实还是类似的,只不过是再把原序列重复的写了几遍,这样大家顺着刚才的思路也可以想到了吧,我们可以先确定在哪一行,再去找数,这个式子怎么算呢?(差值为等差数列的数列求和)高斯的某个定理好像可以算这个,不过,如果不想推公式,还有一种方法:其实这时候我们的最多大已经比较小了我们只需要记录数组然后二分就可以了。

  1-x:a[i]=a[i-1]+ws(i)             (ws表示i的位数)

  原题给的序列:b[i]=b[i-1]+a[i];

  新定义的这个序列:c[i]=c[i-1]+b[i]

  处理一下多二分几次就好了。

  ws的计算是log的,我们不太喜欢,没关系,其实你会发现,大部分情况w是不变的即w[i]=w[i-1],只有i是10的整数次方时才变,那么就好办了,只有记录上一个10的整数次方是多少,然后如果它*10等于这个数,那么就w[i]=w[i-1]+1,当然,w数组可以不开,拿个变量记录一下就好了

  那么我们继续想;

  数组

  d[i]=d[i-1]+c[i]

  可以构造出含意吗,当然可以,表示一群那个类似矩阵的东西的和(能想像出来吧),当然,这样其实我们没必要要些换行,只要放在一行就又是一个序列。

  还有就是其实还是可以继续构造的。

  最后就是原题的代码:

  

#include <cstdio>
const int maxf=+;
long long jl1[][];
int w[];
int ws(int a){
int ans=;
while(a){
ans++;
a/=;
}
return ans;
}
long long P(int len){
long long ans=;
for(int i=;i<=len;i++)
ans*=(long long);
return ans;
}
long long Cl(long long a){
int len=;
long long te=a;
while(a){
len++;
w[len]=a%;
a/=;
}
a=te;
long long ans=;
ans+=(a-P(len-)+)*len;//处理较大的
for(int i=;i<=len-;i++)
ans+=(P(i)-P(i-))*(long long)i;
return ans;
}
long long Cl_(long long a){
int len=;
long long te=a;
while(a){
len++;
w[len]=a%;
a/=;
}
a=te;
long long ans=;
ans+=Cl(P(len-))*(a-P(len-)+)+((a-P(len-)+)*(a-P(len-))/(long long))*(long long)len;
for(int i=;i<=len-;i++)
ans+=Cl(P(i-))*(P(i)-P(i-))+((P(i)-P(i-))*(P(i)-P(i-)-)/(long long))*(long long)i;
return ans;
}
int main(){
int q;
scanf("%d",&q);
for(int i=;i<=q;i++){
long long a;
bool c=;
scanf("%lld",&a);
int l=,r=maxf;
while(l<=r){
int mid=(r-l)/+l;
long long js=Cl_(mid);
if(js==a){
printf("%d\n",mid%);
c=;
break;
}
else if(js>a)
r=mid-;
else
l=mid+;
}//找到在哪个序列里
a-=Cl_(r);
l=,r=maxf;
while(l<=r){
int mid=(r-l)/+l;
long long js=Cl(mid);
if(js==a&&c){
c=;
printf("%d\n",mid%);
break;
}
else if(js>a)
r=mid-;
else
l=mid+;
}
a-=Cl(r);
long long s=r+;//找到在哪个数上
int len=;
while(s){
len++;
w[len]=s%;
s/=;
}
if(c)
printf("%d\n",w[len-a+]);
}
return ;
}

Numerical Sequence(hard version),两次二分的更多相关文章

  1. Numerical Sequence (easy version)

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

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

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

  3. 【二分】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 ...

  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 hard version

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

  6. 【LeetCode】搜索旋转排序数组【两次二分】

    假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定的目标值,如果数组中存在这个目标值, ...

  7. 两道二分coming~

    第一道:poj 1905Expanding Rods 题意:两道墙(距离L)之间架一根棒子,棒子受热会变长,弯曲,长度变化满足公式( s=(1+n*C)*L),求的是弯曲的高度h. 首先来看这个图: ...

  8. ACM_求第k大元素(两次二分)

    求第k大 Time Limit: 6000/3000ms (Java/Others) Problem Description: 给定两个数组A和B,大小为N,M,每次从两个数组各取一个数相乘放入数组C ...

  9. Numerical Sequence (Hard vision) 题解

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

随机推荐

  1. Mybatis基本入门搭建

    一:Mybatis框架概述 1:什么是Mybatis 官方定义: MyBatis 是一款优秀的持久层框架,它支持自定义 SQL.存储过程以及高级映射.MyBatis 免除了几乎所有的 JDBC 代码以 ...

  2. js数据劫持 Object.defineProperty() 作用

    原生js Object.defineProperty() 作用 假设我们有一个obj对象,我们要给他设置一个name属性会这么做 Object.defineProperty()也可以设置对象属性 这个 ...

  3. MySQL 8.0 yum安装和配置

    MySQL 8.0 centos7.5 x86_64 一.yum安装 1.先卸载机器和mysql有关的东西,有的安装了mariab-lib,会对安装有干扰,卸载了它. [root@localhost ...

  4. Servlet中的请求转发

    请求转发时,传递到下一个servlet的request和response可能内存地址不同,但是里面包含的内容是相同的 // servlet1 RequestDispatcher dispatcher ...

  5. Html/css 水平布局居中

    如何设置水平居中显示? 一般的方法是设置宽高,然后以margin去控制,比如:DIV居中的经典方法 本章介绍需要宽度自适应时如何水平居中,以及居中失效的几个点 水平自适应居中 比如设置一个列表水平居中 ...

  6. WINCC 应用与提高(78讲15.98G)视频教程网盘下载

    收集与网络,供参考. https://blog.csdn.net/txwtech/article/details/94225748

  7. VUE+ELEMENT-UI的后台项目封装组件--查询form的封装

    最近项目打算重构,项目的模块几乎都是以后台查询展示的传统的增删改差模式,所以卑微的我想要自己封装一下查询form,先上效果图 子组件页面: <template> <div class ...

  8. jmeter关联的五种方式

    [脚本准备] 这里,我们用dummy取样器来模拟服务器的返回,通过关联获取name的值,然后接口取这个name的值,这就我们就简单模拟了请求间的依赖关系 在取样器中添加dummy取样器 搜索的关键字是 ...

  9. Beta冲刺<6/10>

    这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 Beta冲刺 这个作业的目标 Beta冲刺--第六天(05.24) 作业正文 如下 其他参考文献 ... B ...

  10. 解决Mac中anaconda作图中文异常显示的问题

    说明 本篇主要针对在MAC系统中Anaconda环境下,matplotlib显示不了中文的问题,提出解决Python绘图时中文显示的方法. 运行环境 macOS Mojave 10.14.6 Pyth ...