SPOJ 1182 Sorted bit squence

标签(空格分隔): 数位DP 二分


题目链接

先算出答案1的个数,再二分查找

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long ll;
ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,m,k,c,T,bin[35],num[35],f[35][35];
int dp(int step,int r,int lim)
{
    if(step==0)return r==0;
    if(!lim&&~f[step][r])return f[step][r];
    int x=lim?num[step]:1,res=0;
    res+=dp(step-1,r,lim&&x==0);
    if(r&&x)res+=dp(step-1,r-1,lim&&x==1);
    if(!lim)f[step][r]=res;
    return res;
}
int calc(int x)
{
    for(int i=1;i<=31;i++)num[i]=bool(x&bin[i-1]);
    return dp(31,c,1);
}
int main()
{
    T=read();
    memset(f,-1,sizeof(f));
    bin[0]=1;
    for(int i=1;i<=31;i++)bin[i]=bin[i-1]<<1;
    for(int kase=1;kase<=T;kase++)
    {
        n=read(),m=read(),k=read(),c=0;
        while(1)
        {
            int t=calc(m)-(n==0?0:calc(n-1));
            if(t>k)break;
            k-=t,c++;
        }
        int l=n,r=m,res=n;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(calc(mid)-(n==0?0:calc(n-1))>=k)res=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%d\n",res);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ljzalc1022/p/9018997.html
BIT