POJ3252 RoundNumbers 【组合数学】

本文介绍了一种计算特定范围内二进制数中0的数量超过1的数量的算法。通过分解数字并使用组合数学原理来解决该问题,文章提供了一个C++实现示例,并详细解释了如何针对不同区间进行计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大致题意:

给定left,right,求出[left,right]中有多少数满足如下的性质:化成二进制形式后,0的个数大于等于1

组合数学,各种小边界处理很蛋疼

大致思路是

以10101100为例子,先求[0,10000000)中满足条件的数(想想该怎么求),然后求[100 00000,101 00000),[101 00 000,101 01 000)

[101 01 000,101 01 100)中的,全加起来


一开始思路错了

然后思路对了debug很久发现combination函数写错了。。。

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
long long Combination(long long n,long long r)
{
	if(n==0)
		return 1;
	if(r>n-r)
		r=n-r;
	long long i,j,s=1;
	for(i=0,j=0;i<r;i++)
	{
		s*=(n-i);
		while(s%(r-j)==0&&(r-j)>=2)
		{
			s/=(r-j);
			j++;
		}
	}
	return s;
}
long long cal(long long a)
{
	long long x=1;long long bit=1;
	long long ret=0;
	while(x<=a)
	{
		x<<=1;
		bit++;
	}
	bit--;x>>=1;
//	for(long long i=0;i<=bit/2;i++)
//	{
//		ret+=Combination(bit-1,i);
//	}
	for(long long i=bit-2;i>=0;i--)
	{
		for(long long j=0;j+1<=(i+1)/2 ;j++)
		{
			ret+=Combination(i,j);
		}
	}
	ret+=1;
	long long num1=1,num0=0;
	long long pos=bit;
	while(x>>=1,pos--)
	{
		if(x&a)
			num1++;
		else
			num0++;
		if(x&a)
		{
			for(long long i=pos-1;num0+1+i>=num1-1+pos-1-i && i>=0;i--)
			{
				ret+=Combination(pos-1,i);
			}
		}
	}
	return ret;
}
int main()
{
	#ifndef ONLINE_JUDGE
		freopen("G:/1.txt","r",stdin);
		freopen("G:/2.txt","w",stdout);
	#endif
	long long A,B;
	scanf("%lld%lld",&A,&B);
	printf("%lld\n",cal(B+1)-cal(A));
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值