标签(空格分隔): 数位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;
}
原文地址:https://www.cnblogs.com/ljzalc1022/p/9018997.html
时间: 2024-10-20 02:42:42