zoukankan      html  css  js  c++  java
  • codeforces 460D Little Victor and Set(构造、枚举)

    最近的CF几乎都没打,感觉挺水的一个题,不过自己仿佛状态不在,看题解才知道做法。

    输入l, r, k (1 ≤ l ≤ r ≤ 1012; 1 ≤ k ≤ min(106, r - l + 1)).

    从[l,r]选至多k个数使得选出的数的异或值最小,输出最小异或值和方案。

    分类讨论,首先如果r-l+1<=4,枚举集合解决之。

    先面讨论r-l+1>=5的情况:

    此时有至少5个数可以选择,故至少有连续的4个数满足2x,2x+1,2x+2,2x+3。

    k==1时显然方案为{l}。k==2时,显然方案为{2x,2x+1}。k>=4时,显然方案为{2x,2x+1,2x+2,2x+3}。

    k==3时再另外考虑:

    首先,异或值至多为1(参考k==2)

    我们现在来找异或值可否为0。先假设可以,则显然是选3个数。不妨设x>y>z。

    111...1111

    111...1110

    000...0001

    显然x,y,z前半部分必定是如上这样的,但由于我们要使得x,y,z尽量靠近,所以x,y,z前半部分必然是如下

    11

    10

    01

    之后,每添加一位,有可能是yi=zi=1,xi=0或xi=zi=1,yi=0或xi=yi=1,zi=0。

    由于要x,y,z尽量靠近,所以显然采取yi=zi=1,zi=0。

    所以x,y,z的二进制形式如下

    110...0

    101...1

    011...1

    至此,问题大致解决,剩下的就是些细节问题,问题不大。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <vector>
    using namespace std;
    
    #define ll long long
    
    int cnt(int i){
        int ret=0;
        while(i) i-=i&(-i), ++ret;
        return ret;
    }
    int main(){
        ll l,r;
        int k;
        while(~scanf("%I64d%I64d%d",&l,&r,&k)){
            if(r-l+1<5){
                int n=r-l+1;
                ll ansxor=1ll<<60;
                vector<ll>val;
                for(int i=1;i<(1<<n);++i){
                    ll xx=0;
                    for(int j=0;j<n;++j)
                        if(i&(1<<j)) xx^=l+j;
                    if(xx<ansxor && cnt(i)<=k){
                        ansxor=xx;
                        val.clear();
                        for(int j=0;j<n;++j) if(i&(1<<j)) val.push_back(l+j);
                    }
                }
                printf("%I64d
    ",ansxor);
                printf("%d
    ",val.size());
                for(int i=0;i<val.size();++i) printf("%I64d%c",val[i],i==val.size()-1?'
    ':' ');
            }
            else if(r-l+1>=5){
                if(k==1){printf("%I64d
    1
    %I64d
    ",l,l);continue;}
                if(k==2){
                    if(l&1) l++;
                    puts("1");
                    puts("2");
                    printf("%I64d %I64d
    ",l,l+1);
                }
                else if(k>=4){
                    if(l&1) l++;
                    puts("0");
                    puts("4");
                    printf("%I64d %I64d %I64d %I64d
    ",l,l+1,l+2,l+3);
                }
                else if(k==3){
                    ll x=-1,y,z;
                    for(ll i=3;i<=r;i=i<<1){
                        if((i^(i-1))>=l){
                            x=i;
                            y=i - 1;
                            z=i^(i-1);
                            break;
                        }
                    }
                    if(x!=-1){
                        puts("0");
                        puts("3");
                        printf("%I64d %I64d %I64d
    ",x,y,z);
                    }
                    else {
                        if(l&1) l++;
                        puts("1");
                        puts("2");
                        printf("%I64d %I64d
    ",l,l+1);
                    }
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Python range() 函数用法
    substr
    disable enable 所有其他表关联的外键
    sql with multiply where
    小米开源文件管理器MiCodeFileExplorer-源码研究(7)-Favorite收藏管理和SQLite数据库CRUD
    Centos安装FastDFS+Nginx(一天时间搞定)
    Centos安装FastDFS+Nginx(一天时间搞定)
    小米开源文件管理器MiCodeFileExplorer-源码研究(6)-媒体文件MediaFile和文件类型MimeUtils
    小米开源文件管理器MiCodeFileExplorer-源码研究(6)-媒体文件MediaFile和文件类型MimeUtils
    小米开源文件管理器MiCodeFileExplorer-源码研究(5)-AsyncTask异步任务
  • 原文地址:https://www.cnblogs.com/nextbin/p/3930148.html
Copyright © 2011-2022 走看看