Numerical Sequence(hard version),两次二分
题目:
题意:
已知一个序列:
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),两次二分的更多相关文章
- 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...\), ...
- 【二分】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 ...
- 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 hard version
题目 The only difference between the easy and the hard versions is the maximum value of k. You are giv ...
- 【LeetCode】搜索旋转排序数组【两次二分】
假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定的目标值,如果数组中存在这个目标值, ...
- 两道二分coming~
第一道:poj 1905Expanding Rods 题意:两道墙(距离L)之间架一根棒子,棒子受热会变长,弯曲,长度变化满足公式( s=(1+n*C)*L),求的是弯曲的高度h. 首先来看这个图: ...
- ACM_求第k大元素(两次二分)
求第k大 Time Limit: 6000/3000ms (Java/Others) Problem Description: 给定两个数组A和B,大小为N,M,每次从两个数组各取一个数相乘放入数组C ...
- Numerical Sequence (Hard vision) 题解
The only difference between the easy and the hard versions is the maximum value of \(k\). You are gi ...
随机推荐
- awardRotate转盘插件文字模糊问题和图片加载问题
前言 最近在做一个转盘抽奖页面,使用了awardRotate.js发现字体和图片都有模糊,绘制的时候图片绘制不全,搜索一下之后发现针对awardRotate的解决方法比较少,针对canvas的比较多, ...
- ODEINT 求解常微分方程(4)
import numpy as np from scipy.integrate import odeint import matplotlib.pyplot as plt # function tha ...
- Linux: ssh命令 远程登录
1.查看SSH客户端版本 使用ssh -V命令可以得到版本号.需要注意的是,Linux一般自带的是OpenSSH; $ ssh -V ssh: SSH Secure Shell 3.2.9.1 (no ...
- 【loj - 6516】「雅礼集训 2018 Day11」进攻!
目录 description solution accepted code details description 你将向敌方发起进攻!敌方的防御阵地可以用一个 \(N\times M\) 的 \(0 ...
- [源码解析] GroupReduce,GroupCombine 和 Flink SQL group by
[源码解析] GroupReduce,GroupCombine和Flink SQL group by 目录 [源码解析] GroupReduce,GroupCombine和Flink SQL grou ...
- MFC_VC++_时间获取与保存列表控件内容到文件操作方法
MFC_VC++_时间获取与保存列表控件内容到excel文件操作方法 void CDataView::OnBnClickedBtnExporttoexcel() { CTime time = CTim ...
- [cpp]C++中的析构函数
C++中的析构函数 简介 析构函数(Destructors),是对象的成员函数,没有返回值也没有参数,且一个类只有一个析构函数,当对象被销毁的时候调用,被销毁通常有这么几个情况. 函数执行结束 程序执 ...
- 【SEED Labs】DNS Rebinding Attack Lab
Lab Overview 实验环境下载:https://seedsecuritylabs.org/Labs_16.04/Networking/DNS_Rebinding/ 在这个实验中模拟的物联网设备 ...
- Window下将nginx配置为开机自动启动
前两天看到公司window服务器上面有个nginx在跑,重启服务器后没有自动启动,需要手动运行nginx,甚是麻烦呀 上网找了一下关于将nginx配置为系统服务并且开机自动启动的解决方案,这里mark ...
- CPU明明8个核,网卡为啥拼命折腾一号核?
中断机制 我是CPU一号车间的阿Q,我又来了! 我们日常的工作就是不断执行代码指令,不过这看似简单的工作背后其实也并不轻松. 咱不能闷着头啥也不管一个劲的只管执行代码,还得和连接在主板上的其他单位打交 ...