0和1的熟練

无敌の暗黑魔王發表於2024-06-23

$\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; 
}

相關文章