Problem H Pyro Tubes

本题题目意思是说,有18个灯,亮度分别1,2,4,8,……2^18,总量度为每个灯的亮度和,然后给出一系列总亮度,问每种亮度有几种方法可以在只改变两个灯的明暗状态的前提下转化为所给出的其他比自身亮度大的亮度。

听着比较绕,其实就是将一个数的2进制数只改变其中的两个0或1,使其比原数大,然后找出序列中每个数能转化成序列中其他数的个数。


我们的刚开始思路是判断序列中每个数是否为能由第i个数转化过去,然后记录一共有几个,复杂度为O(n^2),根据输入规模,显然会超时,因此我们要改变策略。

这是我们发现,每个数可转化的数最多只有18*18个,但l最多有250000个,因此我们可以倒着想,遍历每一个x可以转化的数,然后在输入的序列中查找,查找可以用二分查找,因为题目数的是按升序排列的;这样程序的时间复杂度就降为O(nlogn)。

代码如下:

#include<bits/stdc++.h>
using namespace std;

int num[999999];
int serch(int x, int l, int r)//二分查找
{
	if(l > r) return 0;
	if(l == r )
	{
		if(x==num[l]) return 1;
		return 0;
	}
	int q = (l + r)/ 2;
	if(x==num[q]) return 1;
	if(x > num[q])
	{
		return serch(x, q+1, r);
	}
	else
	{
		return serch(x, l, q-1);
	}
}
int main()
{
	int n,tmp,i,j,h,ans;
	int book[555];
	n = 0;
	while(scanf("%d",&tmp) && tmp!= -1)
	{
		num[n++] = tmp;
	}
	int t = 0;
	//打表,num[i]与book[j]按位亦或得到num[i]可以转化为的数
	for(j=0; j<=17; j++)
		book[t++] = (1<<j);
	for(h=0; h<=17; h++)
		for(j=0; j<h; j++)
			book[t++] = (1<<j) + (1<<h);
		
	for(i=0; i<n; i++)
	{
		ans = 0;
		printf("%d:",num[i]);
		for(j=0; j<t; j++)
			if( (num[i]^book[j]) > num[i] && serch(book[j]^num[i], i+1, n-1) )
				ans++;
		printf("%d\n",ans);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值