Topic links: http://codeforces.com/contest/1216/problem/E2
The meaning of problems: there is an infinite length sequence of digits, consisting of 1 1 2 1 2 3 1 ....... 1 2 ... n ..., i.e. repeated 1 to 1,1 to 2 .. ..1 ~ n, give you a k, ask anything of k (1e18) number is
Analysis: First of all, let's count roughly about the number of blocks (a block values a 1 to i) We assume that the length of the i-th block is i (in fact be greater, because to the back, double-digit three digits ...), so calculated, the first n blocks and to achieve 1e18 words, n is approximately 1e9 (arithmetic sequence summation is the complexity of the square), we must find a faster rate find it belongs The first few
Because the first block i + 1 and i is certainly greater than the previous block and, that monocytogenes, we can use two points to address this issue, specific look at the code
Several places difficult to understand:
add the current value is shorter than the length and number, such as when the length is 3, the lengths of all of the number and length of 2 to 189 (1-9,10-99)
cnt * (cnt + 1) / 2 * len We pray because we are a current length, the current number two lengths of up to cnt number of the current length, that is, the arithmetic sequence summation, then take like a len
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=2e5+7; const int N=1e3+7; const int inf=0x3f3f3f3f; ll k; ll get(ll x){ return x*(x+1)/2; } ll sumto(int x,int need){ ll sum=0; ll add=0; ll p= . 1 ; for ( int len = . 1 ;; len ++ ) { IF (P * 10 - . 1 < X) { LL CNT = P * 10 -p; // length Len is the number of digital IF (need) { / / GET (CNT) * len is the length of the total length len numbers, but since each number starts from 1, and the sum of the length of the front there 1,2..len-1, and this is saved add // a total cnt * add a need to add SUM = + + cnt * add GET (CNT) * len; add + CNT = * len; // each add deposit is less than the current length of all lengths and numbers } else sum+=cnt*len; } else { ll cnt=x-p+1; if(need){ sum+=cnt*add+get(cnt)*len; } else sum+=cnt*len; break; } p*=10; } return sum; } int main(){ int q;scanf("%d",&q); the while (q - ) { Scanf ( " % I64d " , & k); int L = . 1 , = R & lt 1E9; int RES = - . 1 ; // find the first module is larger than k and the while (L <= R & lt) { int MID = L + R & lt >> . 1 ; IF (sumto (MID, . 1 )> = K) { RES = MID; R & lt = mid- . 1 ; } the else L = MID + . 1 ; } //cout<<res<<endl; //cout<<sumto(res-1,1)<<endl; k-=sumto(res-1,1); l=1,r=res; int ans=-1; while(l<=r){ int mid=l+r>>1; if(sumto(mid,0)>=k){ ans=mid; r=mid-1; } else l=mid+1; } //cout<<ans<<" "<<k<<endl; k-=sumto(ans-1,0); //cout<<k<<endl; cout<<to_string(ans)[k-1]<<endl; } return 0; }