1. 程式人生 > >牛客寒假算法基礎集訓營6 G 區間或和

牛客寒假算法基礎集訓營6 G 區間或和

轉移 can scan data 直接 org clu span pac

原題鏈接:點我轉移

官方題解的做法:

如果 a=b ,那麽答案 =a ;

否則 aba≠b ,

考慮a和b的二進制表示從高到低第一個不同的位i,

必定b的第i位=1,a的第i位=0。

那麽可以斷定,對於答案的二進制表示,

(1) 比第i位更高的那些位一定跟a相同。

(2) 第i位及比第i位更低的那些位一定為1。

(1)是顯然的,(2)是由於把a中比第i位更低的那些位都置為1得到的數一定在區間[a,b]中。

大佬的ac代碼:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    
long long x,y,m,n; while(~scanf("%lld%lld",&x,&y)) { m=x|y; long long t=1; while(t<=y) { if(x+t<=y)m|=t; t<<=1; } cout << m << endl; } return 0; }

菜雞的我的ac代碼

純粹找規律

#include<bits/stdc++.h>
using namespace std;
int www(long long n,long long m)///找n與m的第一個不同位的位置
{
    int a[70]= {0},b[70]= {0},i=0,j=0;
    while(n)
    {
        a[i++]=n%2;
        n/=2;
    }
    while(m)
    {
        b[j++]=m%2;
        m/=2;
    }
    int k=--i;
          for(; k>=0
; k--) if(a[k]!=b[k]) { break; } return ++k; } long long sss(long long n,int wei)///得到n從wei位開始後面的變十進制得值 { int a[100]= {0},i=0; while(wei--) { a[i++]=n%2; n/=2; } long long ans=0; for(int j=i-1; j>=0; j--) ans=ans*2+a[j]; return ans; } long long poww(int a,int n)///a的n次方 { long long ans=1; while(n--) ans*=a; return ans; } long long aaa(long long n)///找小於n的最大的2的次方值 { long long m=1; while(m<=n) m*=2; return m/2; } int main() { long long n,m; while(cin>>n>>m) { long long ans=aaa(m);///得到小於m的最小的2的次冪的值 if(ans>n)///如果ans在n到m這和區間直接輸出ans*2-1。。這是一個規律。。試出來的 { cout<<ans*2-1<<endl; } else///然後其他情況 { int wei=www(n,m);///取得n與m的二進制從高位開始第一個不同的位的位置 long long shen=sss(n,wei);///得到n二進制wei開始到最後一位變十進制得值 long long an=n+poww(2,wei)-1-shen;///n+2的wei的次方再減去1再減去n的二進制wei位之後的值 cout<<an<<endl; } } return 0; }

牛客寒假算法基礎集訓營6 G 區間或和