CSP-M2 C - 咕咕东的奇妙序列
题目描述 #
咕咕东 正在上可怕的复变函数,但对于稳拿A Plus的 咕咕东 来说,她早已不再听课,此时她在睡梦中 突然想到了一个奇怪的无限序列:112123123412345 …这个序列由连续正整数组成的若干部分构成,其 中第一部分包含1至1之间的所有数字,第二部分包含1至2之间的所有数字,第三部分包含1至3之间的所 有数字,第i部分总是包含1至i之间的所有数字。所以,这个序列的前56项会是 11212312341234512345612345671234567812345678912345678910,其中第1项是1,第3项是2,第20项是 5,第38项是2,第56项是0。咕咕东 现在想知道第 k 项数字是多少!但是她睡醒之后发现老师讲的东西 已经听不懂了,因此她把这个任务交给了你。 输入格式 # 输入由多行组成。
第一行一个整数q表示有q组询问
接下来第i+1行表示第i个输入 ,表示询问第 项数字。 输出格式 # 输出包含q行
第i行输出对询问 的输出结果。
样例输入 #
5 1 3 20 38 56
样例输出 #
1 2 5 2 0
数据点 | q (上限) | k(上限) |
---|---|---|
1,2,3 | 500 | 55 |
4,5,6 | 100 | 1e6 |
7,8,9 | 500 | 1e18 |
解题思路
输入a
利用二分法先找出 a 已满足几段 (1~n) 为一段
a 减去以满足的数量
在求出 a 是那一段中的第几个
Code
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int inf=1e9;
int q;
long long a;
long long find(long long x){
long long m=1,n=0,d=0,f=1;
long long sum=0;
while(1){
m*=10;
d++;
n=m-m/10;
if(x>m-1){
sum+=f*n+d*n*(n-1)/2;
f+=d*n+1;
}else{
n=x-m/10+1;
sum+=f*n+d*n*(n-1)/2;
break;
}
}
return sum;
}
int main(){
scanf("%d",&q);
while(q--){
scanf("%lld",&a);
int l=0,r=1e9,mid=0;
int ans;
long long set;
while(l<=r){
mid=(l+r)/2;
set=find(mid);
if(set<a){
ans=mid;
l=mid+1;
}else{
r=mid-1;
}
}
a-=find(ans);
long long m=1,n=0,d=0,sum=0,ss=0;
while(a){
m*=10;
n=m-m/10;
d++;
if(a>n*d){
sum+=n;
a-=n*d;
}else{
sum+=a/d;
ss=a%d;
break;
}
}
if(ss==0)printf("%lld\n",sum%10);
else{
sum+=1;
while(d!=ss){
d--;
sum/=10;
}
printf("%lld\n",sum%10);
}
}
return 0;
}