[uva 1350]数位dp+二分

题目链接:https://vjudge.net/problem/38405

#include<bits/stdc++.h>
using namespace std;

long long dp[64][2];
int b[64];

long long dfs(int pos,int preok,int pre1)
{
    if (pos==-1) return 1;
    if (preok && dp[pos][pre1]!=-1) return dp[pos][pre1];
    int up=preok?1:b[pos];
    if (pre1) up=0;
    long long ans=0;
    for (int i=0;i<=up;i++)
    {
        if (i<b[pos]||preok) ans+=dfs(pos-1,1,i==1);
        else ans+=dfs(pos-1,0,i==1);
    }
    if (preok) dp[pos][pre1]=ans;
    return ans;
}

long long solve(long long n)
{
    int cnt=0;
    if (n<0) return 0;
    do{
        b[cnt++]=n%2;
        n/=2;
    }while (n);
    return dfs(cnt-1,0,0)-1;
}

int main()
{
    memset(dp,-1,sizeof(dp));
    int t;
    scanf("%d",&t);
    while (t--)
    {
        long long k;
        scanf("%lld",&k);
        long long l=0,r=1000000000000000000ll;
        while (l<r)
        {
            long long mid=(l+r)/2;
            long long res=solve(mid);
            if (res<k) l=mid+1;
            else r=mid;
        }
        int cnt=0;
        do{
            b[cnt++]=l%2;
            l/=2;
        }while (l);
        for (int i=cnt-1;i>=0;i--) printf("%d",b[i]);
        printf("\n");
    }
    return 0;
}

 

posted @ 2017-07-19 18:38  ACMsong  阅读(193)  评论(0编辑  收藏  举报