??????url看这里
大意:给定一个序列:112123123412345...序列的规律能看出来,这里也不细说了。长度小于1e9,多次询问,每次问序列的第k给数字是什么。
思路:
我一开始想着找出每一个数字的规律,事实上它们确实有规律可循,我也确实找到了每一个数字对应的通项,但是我一直没写对,改天再试试。
有一种二阶前缀和的思路:
a【】表示每一个数字对应字符串的长度,比如a[12378]=5;
b【】就表示前a给数字的总长度,b是a的前缀和
c是b的前缀和,表示的就是1,12,123,12345...的对应的长度。比如c【10】=4.
那么对于每一次的询问,先二分c找到它对应在哪一个1-x的区间内,再二分b找到它在1-x的区间里属于哪一个数字,找到对应的数字后再枚举一下位数就是对应的答案了。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=1e5+10;
ll t,n;
ll a[N],b[N],c[N];
int main()
{
for(int i=1;i<=N;++i)
{
ll sd=i;
while(sd)
{
a[i]++;
sd/=10;
}
b[i]=b[i-1]+a[i];
c[i]=c[i-1]+b[i];
}
cin>>t;
while(t--)
{
cin>>n;
ll p1=lower_bound(c+1,c+1+N,n)-c;//第几个1-x的序列
n-=c[p1-1];//在该序列中对应的长度
ll p2=lower_bound(b+1,b+1+N,n)-b;//找到对应的数字
n-=b[p2-1];
string ss="";
ss+=to_string(p2);
cout<<ss[n-1]<<endl;
}
return 0;
}
|