Round Numbers POJ - 3252

原题链接
考察:数位dp
思路:
  入门题(然后做了一个小时)
  这里预处理方案数是用组合数.如果我们直接套模板会发现答案不对,因为我们不同数字的二进制位数不同,前导零不应该被计入.
  先算出n有的二进制位数符合条件个数,然后再计算二进制位数比n小的即可.

Code

#include <iostream> 
#include <cstring>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 34;
LL C[N][N];
int l,r;
void init()
{
	for(int i=0;i<N;i++)
	  for(int j=0;j<=i;j++)
	   if(!j) C[i][j] =1;
	   else C[i][j] = C[i-1][j]+C[i-1][j-1]; 
}
LL dp(int n)
{
	if(!n) return 0;
	vector<int> v;
	int sum[2];
	sum[0] = 0,sum[1] = 1;
	while(n) v.push_back(n%2),n/=2;
	LL res = 0;
	for(int i=v.size()-2;i>=0;i--)
	{
		int x = v[i];
		if(x)
		{
			int cnt = sum[0]+1,maxn;
			maxn = i+cnt-sum[1]>>1;
			for(int j=0;j<=maxn;j++) res+=C[i][j];
		}
		sum[x]++;
		if(!i&&sum[0]>=sum[1]) res++;
	}
	for(int i=2;i<v.size();i++)
	  for(int j=i+1>>1;j<i;j++) res+=C[i-1][j];
	return res;
}
int main()
{
	init();
	while(scanf("%d%d",&l,&r)!=EOF)
		printf("%lld\n",dp(r)-dp(l-1));
	return 0;
}
posted @ 2021-05-29 15:23  acmloser  阅读(30)  评论(0编辑  收藏  举报