タイトル:
ググドンの素晴らしいシーケンスタイトル:
入力:
出力:
サンプル:
問題解決のアイデア:この問題は依然として非常に困難です。主にデータが大きすぎるため、接頭辞を使用して最初の6つのポイントしか渡せない場合、1e18は冗談ではなく、数値を組み立てることができません。これが私の考えです:最初に、最初にサイズ8の配列を作成し、1〜10の数値を格納します^ I:たとえば
、配列の最初の要素は
112123123412345 ... 123456789サイズは45 です
配列の2番目の要素は
112123 ... 123 ... 9123 ... 10123 ... 11 ... 123 ... 99から99
第三の要素999
8つの要素(要素が1E18第より大きいされているため、そのため第8要素まで)まで
I少ないkより得Kを減算した後最大の要素。
現時点では、残りのkは123 ...(10 ^ I)123 ....(10 ^ i + 1)...各グループの最後の要素の数(つまり、123 ... x、xが1の後)同じです。その後、kを使用して、各グループの要素の数を、kがそのグループの要素の数よりも小さくなるまで継続的に減算しますが、kが大きすぎるとタイムアウトになることに注意してください。ここで、二分法を使用しましたこの選択の時間を最適化しました;残りは123 ... xのグループであり、それらのk番目のものは さて、ここでは再帰的な方法を使用して、最初にkと9を比較し、それを9より大きい値と比較し、次に180(10、11、... 99合計180ビット)と比較してから、比較を続けます。。。それ以下になるまで、残りの要素の数が同じになるまで(最初の要素は10のi乗でなければならない)、kを知っているだけです。
コード:
#include<iostream>
#include<cmath>
using namespace std;
long long t[17]={0};
long long h[17]={0};
long long t1[17]={0};
void solve()
{
h[0]=1;
for(int i=1;i<=18;i++)
{
h[i]=h[i-1]*10;
}
t[0]=0;
t1[0]=0;
for(int i=1;i<=16;i++)//t1[i]存的是从1-10^i-1的元素的个数
{
t1[i]=t1[i-1]+i*(h[i]-h[i-1]);
}
for(int i=1;i<=8;i++)//t[i]存的就是从组1到组123...10^1-1的元素的个数
{
t[i]=t[i-1]+(h[i]-h[i-1])*t1[i-1]+i*(h[i]-h[i-1])*(h[i]-h[i-1]+1)/2;
}
}
long long sol1(long long k,int num)
{
long long t=(h[num]-h[num-1])*num;
if(k<=t)//小于等于的情况,这时剩下的元素的位数相同,且第一个元素和k已经知道
{
long long k1=(k-1)/num;//这里就是求第k的数字
long long k2=k%num;
long long n=h[num-1]+k1;
if(k2==0)
{
n=n%10;
return n;
}else
{
long long u=n;
int total=0;
while(u>0)
{
u=u/10;
total++;
}
total=total-k2;
for(int i=0;i<total;i++)
{
n=n/10;
}
n=n%10;
return n;
}
}else//大于前去递归
{
k=k-t;
return sol1(k,num+1);
}
}
long long sol(long long k)
{
long long p;
for(int i=8;i>=0;i--)
{
if(t[i]<=k)
{
k=k-t[i];
p=i;
break;
}
}
if(k==0){return 9;}//减去那个最大的,如果为0直接返回9就行
long long p1=t1[p];//这个是减去的那个从1-10^i-1的元素的个数
p++;
while(1)
{
p1+=p;//这个是1-10^i的元素的个数
long long l=0,r=1000000000;
while(l+1<r)//二分
{
long long mid=(l+r)/2;
long long tt=mid*p1+p*(mid-1)*mid/2;
if(k>tt)
{
l=mid;
}else
{
r=mid;
}
}
k=k-(l*p1+p*(l-1)*l/2);//减去,之后剩下的就是123....x
k=sol1(k,1);//判断
return k;
}
}
int main()
{
solve();
int q;
cin>>q;
while(q--)
{
long long k;
cin>>k;
long long h1=sol(k);
cout<<h1<<endl;
}
}