牛客寒假算法基础集训营6 G 区间或和

本文深入探讨了在给定二进制表示的区间[a, b]内寻找最大值的方法,通过分析a和b的二进制表示,确定了答案的二进制结构特征。提供了两种AC代码实现方案,一种简洁高效,另一种通过详细步骤找规律解决,适合初学者理解。

原题链接:点我转移

官方题解的做法:

如果 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;
}

 

转载于:https://www.cnblogs.com/tp25959/p/10349043.html

### 关于2020年牛客寒假算法基础集训营中的欧几里得算法 在2020年的牛客寒假算法基础集训营中,确实存在涉及欧几里得算法的相关题目。具体来说,在第四场竞赛的第一题即为“A. 欧几里得”,该题目的核心在于利用扩展欧几里得定理来解决问题[^5]。 #### 扩展欧几里得算法简介 扩展欧几里得算法主要用于求解形如 ax + by = gcd(a, b) 的线性不定方程的一组特解(x,y),其中gcd表示最大公约数。此方法不仅能够计算两个整数的最大公因数,还能找到满足上述条件的具体系数xy。 对于给定的数据范围较小的情况可以直接通过递归来实现;而对于较大数据则需考虑效率优化问题。下面给出了一段基于C++语言编写的用于解决此类问题的模板代码: ```cpp #include<bits/stdc++.h> #define int long long using namespace std; // 定义全局变量存储结果 int x, y; void ex_gcd(int a, int b){ if(b == 0){ x = 1; y = 0; return ; } ex_gcd(b, a % b); int tmp = x; x = y; y = tmp - (a / b) * y; } ``` 这段程序实现了经典的扩展欧几里得算法逻辑,并且可以作为处理类似问题的基础工具函数调用。 #### 实际应用案例分析 回到原题本身,“A. 欧几里得”的解答思路就是先预处理斐波那契数列前若干项数值存入数组`a[]`内以便快速查询,之后针对每一次询问直接输出对应位置处两相邻元素之即可得出最终答案。这实际上巧妙运用到了广为人知的裴蜀定理——任意一对互质正整数都可由它们自身的倍数组合而成,而这里正是借助了这一性质简化了解决方案的设计过程。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值