PKU 1019 Number Sequence

問題

11212312341234512345612345671234567812345678912345678910123456789101112345678910...
と続く数列がある。

この数列のi番目の数字を求めよ。

制約条件

i≦2147483647

方針

i桁までの数の列を書き終えたときの列の長さをlen[i]とする。
(1121231213412345123456...123456789の長さがlen[0])
これは、len[i - 1]と、等差数列の和の公式から計算できる。


するとlen[i]との比較によって、何桁の数字までが列に含まれるかがわかる。
次にその列において何番目の数であるかを求める。
これは等差数列の和の公式を二分探索すればいい。


今、112123...nという列のk番目の数字を求めたいことになっているので、
k番目の数字が何桁の数であるかを求める。
それで、その桁の何番目の数字に含まれているかを求めて、
その数字のその番目の数字を求めてやればいい。

ソースコード

const int SZ = 7;
ll len[SZ], n[SZ], len2[SZ], pw[30];
int a[SZ];

void solve(ll k){
	int keta = 0;
	while(k >= len[keta]) k -= len[keta++];
	
	ll lo = 0, hi = n[keta], mid;
	while(lo + 1 < hi){
		mid = (lo + hi) / 2;
		if(mid * a[keta] + (keta + 1) * mid * (mid + 1) / 2 <= k) lo = mid;
		else hi = mid;
	}
	k -= lo * a[keta] + (keta + 1) * lo * (lo + 1) / 2;
	
	int keta2 = 0;
	while(k >= len2[keta2]) k -= len2[keta2++];
	
	char digit[30];
	sprintf(digit, "%lld\n", pw[keta2] + k / (keta2 + 1));
	
	k %= keta2 + 1;
	printf("%c\n", digit[k]);
}

int main()
{
	rep(i, SZ){
		a[i] = i ? a[i - 1] + n[i - 1] * i : 0;
		n[i] = i ? n[i - 1] * 10 : 9;
		len[i] = a[i] * n[i] + (i + 1) * n[i] * (n[i] + 1) / 2;
		
		len2[i] = (i + 1) * n[i];
	}
	pw[0] = 1;
	rep(i, 29) pw[i + 1] = pw[i] * 10;
	
	int cs;
	cin >> cs;
	while(cs--){
		ll k;
		cin >> k;
		solve(k - 1);
	}
	return 0;
}