[HDU5969]最大的位或

題目

B君和G君聊天的時候想到了以下的問題。
給定天然數\(l\)\(r\) ,選取\(2\)個整數\(x,y\)知足\(l \leq x \leq y \leq r\),使得\(x|y\)最大。
其中\(|\)表示按位或,即\(C,C++,Java\)中的\(|\)運算。
Input
包含至多\(10001\)組測試數據。
第一行有一個正整數,表示數據的組數。
接下來每一行表示一組數據,包含兩個整數\(l,r\)
保證\(0 \leq l \leq r \leq 1018\)
Output
對於每組數據輸出一行,表示最大的位或。
Sample Input
5
1 10
0 1
1023 1024
233 322
1000000000000000000 1000000000000000000
Sample Output
15
1
2047
511
1000000000000000000c++

解說

題意極其容易理解。
平常習慣先寫個暴力試試,意料之中的\(T\)了。沒辦法,畢竟每次詢問都是\(O(n^2)\)
接下來我思路斷了,因而瞎試,把\(l\)\(r\)每一個數挨個位或一遍,結果全部樣例都對上了。因而我開始思考這會不會就是正解?好像確實是呢,位或是隻要兩個數同一位有一個是\(1\)那麼結果就是\(1\),那麼我全位或一遍就至關於找了這兩個數之間都有哪些位出現了\(1\)。雖然題目問的是找兩個數,但稍微想一下就能夠發如今這兩個數之間是確定能夠找到把出現\(1\)的位都涵蓋的兩個數的。如今的單次時間效率是\(O(n)\)
\(O(n)\)的時間效率還能過不了?天理難容!交……\(T\)了。
看來要麼是還有常數級效率的方法要麼就是\(O(logn)\)的方法。常數級不太可能,那麼就只能試着把剛纔的思想改爲\(O(logn)\)的方法,那確定用到位運算。
和剛纔作法等價的作法就是在\(r\)的範圍內枚舉每一位的\(1\),這樣就至關於剛纔的找\(1\)操做了。
終於\(A\)了。測試

代碼

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;//記得開long long
ll read(){
   ll s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
} 
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        ll l,r,tool=1,move=0;//tool就是枚舉用的,move表示如今在第幾位
        l=read(); r=read();
        while((l|(tool<<move))<=r){
        	l|=(tool<<move);
        	move++;//左移
		}
        printf("%lld\n",l|r);
    }
    return 0;
}

幸甚至哉,歌以詠志。spa

相關文章
相關標籤/搜索