Problem H Pyro Tubes

来源:互联网 发布:淘宝海外直购 编辑:程序博客网 时间:2024/05/20 10:15

本题题目意思是说,有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;}

原创粉丝点击