1. 程式人生 > >Codeforces Round #247(Div. 2) D. Random Task 二分+字首和

Codeforces Round #247(Div. 2) D. Random Task 二分+字首和

D. Random Task time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output

One day, after a difficult lecture a diligent student Sasha saw a graffitied desk in the classroom. She came closer and read: "Find such positive integer n, that among numbers n + 1, n + 2, ..., n there are exactly m numbers which binary representation contains exactlyk

 digits one".

The girl got interested in the task and she asked you to help her solve it. Sasha knows that you are afraid of large numbers, so she guaranteed that there is an answer that doesn't exceed 1018.

Input

The first line contains two space-separated integers, 

m and k (0 ≤ m ≤ 1018; 1 ≤ k ≤ 64).

Output

Print the required number n (1 ≤ n ≤ 1018). If there are multiple answers, print any of them.

Examples input
1 1
output
1
input
3 2
output
5

題意:

給的m和k,找到一個n,使得區間[n+1,2*n]裡的數中,恰好有m個數滿足要求:該數的二進位制表示裡恰好有k個1.

題解:

在k相同的情況下,n單調,可以二分。

重點是求出某個區間滿足要求的數的個數。

我們設cal(x)為區間[0,x]中,二進位制表示中1個個數為k的數的個數,那麼對於一個二分的答案Mid,對應的[Mid+1,2*Mid]滿足要求的數的個數為cal(2*Mid)-cal(Mid).

例如二進位制x=101101 k=3

從高位到底為列舉每一位i:第一位為1,將其置0後,後面可以有任意k個1,故res+=Com(i,k-cnt),Com為組合數,cnt為該位前面的1的個數。第2位為0,跳過;第3位為1,

將該置0,則前面有2個1被置0,則後面還要新增k-2個1。res+=Com(i,k-2),依次計算。

/****************
*PID:431d div2
*Auth:Jonariguez
*****************
*/
#define lson k*2,l,m
#define rson k*2+1,m+1,r
#define rep(i,s,e) for(i=(s);i<=(e);i++)
#define For(j,s,e) For(j=(s);j<(e);j++)
#define sc(x) scanf("%d",&x)
#define In(x) scanf("%I64d",&x)
#define pf(x) printf("%d",x)
#define pfn(x) printf("%d\n",(x))
#define Pf(x) printf("%I64d",(x))
#define Pfn(x) printf("%I64d\n",(x))
#define Pc printf(" ")
#define PY puts("YES")
#define PN puts("NO")
#include <stdio.h>
#include <string.h>
#include <string>
#include <math.h>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef int Ll;
Ll quick_pow(Ll a,Ll b,Ll MOD){a%=MOD;Ll res=1;while(b){if(b&1)res=(res*a)%MOD;b/=2;a=(a*a)%MOD;}return res;}

const int maxn=100000+10;
LL m,k;

LL Com(LL n,LL m){
    if(m==0) return 1LL;
    LL res=n--,i;
    for(i=2;i<=m;i++){
        res*=n;res/=i;
        n--;
    }
    return res;
}


LL cal(LL n){
    LL res=0,i,cnt=0;
    for(i=62;i>=0;i--){
        if((n>>i)&1){
            if(k-cnt>=0)
                res+=Com(i,k-cnt);
            cnt++;
        }
    }
    return res;
}


int main()
{
    int i,j;
    while(scanf("%I64d%I64d",&m,&k)!=EOF){
        LL l=1,r=1e18,Mid,res=-1;
        while(l<r-1){
            Mid=l+(r-l)/2;
            LL temp=cal(2*Mid)-cal(Mid);
            if(temp==m){
                res=Mid;break;
            }else if(temp<m)
                l=Mid+1;
            else r=Mid;
        }
       // printf("cal=%I64d\n",cal(2));
        if(res>=0)
            printf("%I64d\n",res);
        else printf("%I64d\n",l);
    }
    return 0;
}