[机房测试] number

Description

给定 \(m\leq 10^18,k\leq 64\),求出一个正整数 \(n\) 使得 \(n+1 \sim 2n\) 中恰好有 \(m\) 个数恰好有 \(k\)\(1\),以及有多少个这样的数。

Solution

考场上根本没什么思路。

所以首先应该打个表,然后观察到 \(f(i,k)\) 表示 \(i+1 \sim 2i\) 中恰有 \(k\)\(1\) 的数的个数是有单调性的,实际上也容易证明:

\[f(i+1,k)-f(i,k)=[popcount(2i+1)=k]+[popcount(2i+2)=k]-[popcount(i+1)=k] \]

容易发现 \(2i+2\)\(i+1\)\(popcount\) 总是相等的,所以一定有 \(f(i,k)\) 关于 \(i\) 是单调不降的。那么就可以二分出一个 \(i\) 的上下界。

\(f(i,k)\) 的值可以直接数位 dp 求出,注意特判 \(k=1\) 有无限种 \(i\) 的情况。

#include<stdio.h>
#include<algorithm>
using namespace std;

typedef long long ll;

inline ll read(){
    ll x=0,flag=1; char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')flag=0;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
    return flag? x:-x;
}

bool a[64];
int K,tp=0;
ll dp[64][64];

ll dfs(int st,int k,bool lim){
    if(st==63) return !k;
    if(!lim){
        ll &ret=dp[st][k];
        if(~ret) return ret; else ret=0;
        for(int i=0;i<2;i++)
            ret+=dfs(st+1,k-i,0);
        return ret;
    }else{
        ll ret=0;
        for(int i=0;i<=a[st];i++)
            ret+=dfs(st+1,k-i,i==a[st]);
        return ret;
    }
}

ll check(ll x){
    for(int i=0;i<63;i++) a[i]=(x>>(62-i))&1;
    reverse(a+1,a+1+tp); return dfs(1,K,1);
}

int main(){
    freopen("number.in","r",stdin);
    freopen("number.out","w",stdout);
    for(int i=0;i<64;i++)
        for(int j=0;j<64;j++) dp[i][j]=-1;
    int T=read();
    while(T--){
        ll m=read(); K=read();
        if(K==1)
            printf("2 -1\n");
        else{
            ll l=1,r=2e18,L=2e18;
            while(l<=r){
                ll mid=(l+r)>>1;
                if(check(mid<<1)-check(mid)>=m)
                    L=mid,r=mid-1;
                else l=mid+1;
            }
            l=1,r=2e18; ll R=1;
            while(l<=r){
                ll mid=(l+r)>>1;
                if(check(mid<<1)-check(mid)<=m)
                    R=mid,l=mid+1;
                else r=mid-1;
            }
            printf("%lld %lld\n",L,R-L+1);
        }
    }
}
posted @ 2021-10-30 07:37  Kreap  阅读(24)  评论(0编辑  收藏  举报