返回顶部

0和1的熟练

$\quad $ 想不出来了,遂打表。
$\quad $ 受到了luobotianle的启发,就依据其建议学上了分块打表。

0与1的熟练
$\quad $ 问 \(L\)\(R\) 之间,在二进制表示下(无前导\(0\)),\(0\) 的个数比 \(1\) 的个数多的数的个数。
$\quad $ 那么我们就可以以 \(5e5\) 为块长来打表。

打表程序
#define yhl 0
#include<bits/stdc++.h>
using namespace std;
const int N=32,p=5e5;
bitset<N>bit;
int l,r,ans,ansl=0,cntl=0;
int main(){
	freopen("biao.out","w",stdout);
	for(register int i=1;i<=2e9;i=-~i){
		bit=i;int cnt=0;
		int le=ceil(log2(i))+(ceil(log2(i))==log2(i));
		for(int j=0;j<=le-1;j=-~j)if(bit[j]&&((++cnt)<<1>le))break;
		if((cnt<<1)<=le)ans++;
		if(!(i%p)){
			printf("%d,",ans-ansl),ansl=ans;
			if(++cntl==40)putchar('\n'),cntl=0;//每40个数换行,方便观看。 
		}
	}
    return yhl;
}
#define yhl 0
#include"bits/stdc++.h"
using namespace std;
const int N=5e5;
bitset<33>bit;
int biao[4005]={
	//此处省略100行打表代码 
};
int l,r,ans;
bool check(int x){
	if(!x)return 0;
	int le=ceil(log2(x))+(ceil(log2(x))==log2(x));
	bit=x;int cnt=0;
	for(int i=0;i<le;i++)if(!bit[i])cnt++;
	return ((cnt<<1)>=le);
}
int main(){
	scanf("%d%d",&l,&r);
	int bl=(l-1)/N+1,br=(r-1)/N+1;
	if(bl^br){
		for(int j=bl+1;j<=br-1;j++)ans+=biao[j];
		for(int j=l;j<=bl*N;j++)ans+=check(j);
		for(int j=br*N-N+1;j<=r;j++)ans+=check(j);
	}else for(int i=l;i<=r;i++)ans+=check(i);
	printf("%d",ans);
	return yhl; 
}
posted @ 2024-06-23 11:54  无敌の暗黑魔王  阅读(31)  评论(0编辑  收藏  举报