zoukankan      html  css  js  c++  java
  • HDU

    http://acm.hdu.edu.cn/showproblem.php?pid=5969 (合肥)区域赛签到题。。。orz

    题意:给你l,r,求x|y的max,x,y满足l<=x<=y<=r.

    题解:初始想法是找到形如(111,1000)、(11111,100000)····这样的进位点,一旦区间里有这种相邻两位进位的或一下就可以得到1111····,必然最大。(后面的是瞎搞)如果区间里没有,说明l,r二进制长度一样,于是从最高位往下找,一直找到不一样的一位,变成了前一种有进位的情况。这个算法的正确性完全没有证明,但是头铁。。结果一直wa。

    正确的想法是对于二进制下r的每个0,去找在l,r区间是否存在一个数K可以把这个0变成1,顺便把剩下所有的数变成1.如果可以就输出变化后的数。

    算法是从r的二进制最高位开始往底扫,遇到一个0,就找一个最大的数k,使得k|r将这一位的0变成1。然后判断一下k是否大于 l 。

    找k的方法是将从r的第一个0开始的将其后面的数组全部变为0,然后-1,直观地看就是将第一个0前面的1变成0,后面全部变成1.

    保存r二进制用一个数组,清零的时候维护一个sum简化操作。

    ac代码

    #define    _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    ll l, r;
    ll pow(ll x) {
        if (x == 0)return 1;
        
        ll s = 1;
        while (x--) {
            s <<= 1;
        }
        return s;
    }
    ll ans[5005];
    
    int main(){
        int t;
        cin >> t;
        while (t--) {
            cin >> l >> r;
            ll sum=0;
            ll bit = 0,  rr = r;
            int cnt = 0;
            while (rr) { ans[cnt++] = (rr & 1); rr >>= 1; }
    
            for(int i=0;i<cnt;i++){
                if (ans[i] == 0) {
                    ll k = r - sum - 1;
                    if (k >= l)ans[i] = 1;
                }
                else { sum += pow(i); }
            }
            sum = 0;
            for (int i = 0; i < cnt; i++){ sum += pow(i)*ans[i]; }
            cout << sum << endl;
    
        }
    }
    成功的路并不拥挤,因为大部分人都在颓(笑)
  • 相关阅读:
    C#:类的学习
    SilverLight xaml页面跳转方法
    C#对象生命周期(转载)
    jquery常用的方法
    关于Java日期简单应用
    Compilingphpwithcrypt()
    SSI使用详解
    实例解析:从IIS的ASP迁移到APACHE的PHP
    三步搞定phpwind的静态化部署
    Informix Dynamic Server 中的分布式事务
  • 原文地址:https://www.cnblogs.com/SuuT/p/8551584.html
Copyright © 2011-2022 走看看