Codeforces 1216E Numerical Sequence 二分

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;
}

 

Guess you like

Origin www.cnblogs.com/qingjiuling/p/11574054.html