number (special properties)

Face questions



$ solution: $

First $ wch $-half said they would not feel positive solution is to use approximation ah!

First we prove a thing :( examination room can directly hit the table to find the law)

  1. For any odd n-$ $, provided it is the next number in the binary K $ $, since the end of the odd binary $ $ 1, so there are: $ n-1 $ is an even number, and $ n-1 $ binary the next number is $ k-1 $
  2. Then we set $ f (n, k) $ represent at $ 0,1,2 ... n $ binary count exactly the number of $ k $ a $ 1 $, the subject of the request is not difficult to find $ f (2n, k) -f (n, k) $
  3. We will be $ 0 to $ number of n are doubling the $ 0,2,4,6 ..... 2n $ binary so that only the left one, a number unchanged. Therefore, $ f (n, k) $ $ 0 ~ 2n $ equal to the number of even-qualified.

Further we can give the title required by the third point $ f (2n, k) -f (n, k) $ $ 0 ~ 2n $ is the odd number of qualified! Then combine the first proof is required to know the number of $ 0 ~ 2n-2 $ next is an even binary number $ k-1 $, we use a third reverse again prove that we can get $ f (2n, k) -f (n, k) = f (n-1, k-1) $. (Note that the definition of the function $ f $, it can be seen having a monotonic)

Then find the subject becomes a meaning that $ n-$ $ 0 ~ n-1 $ $ m $ exactly in number, which is the next number in the binary $ k-1 $. Since then $ f (n-1, k-1) $ monotonic, we know that all qualifying $ n $ are in a period of range! As long as we can find around the boundary of this range!

怎么求?我们用倍增逼近法,设 $ f[i][j] $ 表示二进制下一的个数为 $ i $ 的数在 $ 0~2^j $ 内有多少个。为什么用倍增呢?因为 $ 2^j+k $ 和 $ k $ 二进制下一的个数前者是后者+1(前提 $ k<2^j $ ),这个很容易证明因为前者二进制下最左端多了个一而已。然后我们将 $ f[i][j] $ 这个数组打出表,发现它和组合数很像,当然也可以证明其求法和组合数基本一致。



$ code: $

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>

#define ll long long
#define db double
#define rg register int

using namespace std;

ll f[65][65];

inline ll qr(){
    register char ch; bool sign=0; register ll res=0;
    while(!isdigit(ch=getchar()))if(ch=='-')sign=1;
    while(isdigit(ch))res=res*10+(ch^48),ch=getchar();
    if(sign)return -res; else return res;
}

int main(){
    for(rg i=0;i<=61;++i) f[0][i]=1;
    for(rg i=1;i<=61;++i)
        for(rg j=i;j<=61;++j)
            f[i][j]=f[i][j-1]+f[i-1][j-1];
    rg t=qr();
    while(t--){
        register ll n=qr(),k=qr()-1,sn=n,sk=k,l=0,r=0;
        if(!n){printf("1 %lld\n",((ll)1<<(k))-1); continue; }
        if(k==0){printf("1 -1\n"); continue; }
        for(rg i=61;i>=0;--i){
            if(n<=f[k][i])continue;
            l+=(ll)1<<i; n-=f[k][i]; --k;
        } n=sn; k=sk;
        for(rg i=61;i>=0;--i){
            if(n<f[k][i])continue;
            r+=(ll)1<<i; n-=f[k][i]; --k;
            if(k<0){ while(--i)r+=(ll)1<<i; break;}
        }printf("%lld %lld\n",l+1,r-l);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/812-xiao-wen/p/11318887.html