GYM 101128H Sheldon Numbers

原题如




Description 
问区间[x,y]中有多少数的二进制表示是ABAB..AB型或者A型的,其中A是n个1,B是m个0,n, m > 0 
Input 
两个整数x和y(0<=x,y < 2^63) 
Output 
输出[x,y]中有多少满足条件的数 
Sample Input 
1 10 
Sample Output 
10 


思路:先构建模板,像110, 1110, 或全是1等等,把所有的满足要求的数求出来存在一个vector里,然后总共满足的数才四千多,所以之后进行枚举看有多少满足要求的数在指定区间即可。


代码中有思路,

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const unsigned LL inf = pow(2, 63);
vector<LL> vt;		//用vector存满足要求的数,不需要用set,无重 
vector<LL>::iterator it;
void add(int i, int j){
	LL k = 1, ans = 0, x, p;
	int c = 63/(i+j), a, b, flag = 1;
	while(c--){	//假如模板是110,那么110110也是可以的,这样用c可以表示63位内可以用这个模板的数的个数 
		if(flag) a = j-1, flag = 0;//由于k初值为1表示2^0,消耗了一次0,所以第一次0的个数减1,不明白模拟一遍便知 
		else a = j;
		b = i;
		while(a--) k *= 2;
		while(b--){
			k *= 2;
			ans += k;
		}
		vt.push_back(ans);		//得到的ans形如110,110110,110110110 
		x = 1, p = 1;
		for(int l = 1; l < i; ++l){
			x *= 2;
			p += x;
		}
		LL op = (ans<<i) + p;
		if(op >= 0)	//判断数是否超long long范围,超范围的数会变为绝对值很大的负数 
			vt.push_back(op);	//(ans<<i)+p形如11011, 11011011
	} 
}
void init(){
	for(int i = 1; i <= 63; ++i)
	for(int j = 1; j <= 63-i; ++j)
		add(i, j);		//i,j模拟模板的1个数和0个数 
	LL k = 1, x = 1;
	vt.push_back(1);	//把全是1的情况也加进去 
	for(int i = 1; i < 63; ++i){
		k *= 2;
		x += k;
		vt.push_back(x);
	}
}
int main(){
	LL a, b, ans = 0;
	init();
	cin >> a >> b;
	for(it = vt.begin(); it != vt.end(); ++it){	//遍历一次求在这个范围的满足要求数的个数 
		if(*it >= a && *it <= b) ++ans;
	}
//	cout << inf << endl;
//	cout << vt.size() << endl;
	cout << ans << endl;
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值