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;
}
posted @ 2018-05-10 12:09  LJZ_C  阅读(112)  评论(0编辑  收藏  举报