zoukankan      html  css  js  c++  java
  • Atcoder D

    题目链接:http://agc015.contest.atcoder.jp/tasks/agc015_d

    题意:给出两个数b,a(a>=b)问{a,a+1,....,b}的集合内取任意数求或运算最多能够表示多少个数。

    题解:数据很吧不用想着暴力,主要是位运算一般都会想到用二进制来写。具体的写法详见代码注释,不好表达。

    #include <iostream>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    ll getnum(ll A , ll B) {
        int len1 , len2;//len1表示第一个大于A的2进制位数,len2表示第一个大于B的二进制位数
        if(A == B) return 1;
        for(len1 = 0 ; ((ll)1 << len1) <= A ; len1++);
        for(len2 = 0 ; ((ll)1 << len2) <= B ; len2++);
        if(len2 < len1) {
            ll t;
            for(t = len1 - 2 ; t >= 0 ; t--)
                if(((ll)1 << t) & A) break;//先找到A中从大到小第二个1的位置。
            if(t == -1) t = 0;
            else t = ((ll)1 << (t + 1)) - 1;
            if(B <= t + 1) return ((ll)1 << len1) - B;//显然能组成(1 << (len1 - 1)|t)~ B 的所有情况。然后最大能组合到(1 << len1 - 1)~(1 << (len1 - 1))|B)由于t+1比B大所以两个区间是相交的所以直接1 << len1 - B
            return (((ll)1 << (len1 - 1) | t) - B + 1) + (((ll)1 << len1) - 1 - (((ll)1 << (len1 - 1)) + B) + 1);//同理只不过集合不相交,所以要分两个集合算一下
            
        }
        return getnum(A ^ ((ll)1 << (len1 - 1)) , B ^ ((ll)1 << (len2 - 1)));
        //位数相同就去掉首位继续比较,去掉首位的方法就是求一下异或。
    }
    int main() {
        ll A , B;
        cin >> B >> A;
        cout << getnum(A , B) << endl;
        return 0;
    }
    
  • 相关阅读:
    Pika的设计及实现
    高性能网络编程
    C语言的结构体
    消息队列库——ZeroMQ
    Diffie-Hellman密钥交换算法
    mysql-proxy 读写分离
    位运算
    分布式学习之一:事务
    Redis Cluster
    SpringBoot整合ActiveMQ,看这篇就够了
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/6937250.html
Copyright © 2011-2022 走看看