zoukankan      html  css  js  c++  java
  • [二分] Codeforces 1271E Common Number

    题目链接

    题解

    容易发现,对于给定的(N),假设(y)(k)个互异的(path_j)中出现,那么在([1,n])内一定存在且只存在(k)个数,这(k)个数的二进制以(y)的二进制为前缀,或者若(y)的二进制最低位为(0)时,(y)的最低位也可进(1),然后再以(y)为前缀。

    不妨令(Judge(x))表示在([1,N])内以(x)的二进制为前缀的数的数量,即出现过(x)的互异的(path_j)的数量。那么我们从(x=1)开始,不断地将(x)左移,直到(Judge(x) < K),即可获得(Ans)的二进制最大长度。然后我们在这个(x)的基础上,从(x)的二进制高位到低位不断地尝试把(0)变成(1),若改变后(Judge(x))仍大于(K),则保持改变,否则继续判断下一位。

    对于函数(Judge(x)),我们按在(x)后添加的二进制位数分开计算,假设现在我们要在(x)后添加一个长为(Len)的后缀,我们可以用二分算出长为(Len)的最大的后缀,即为在(x)后添加长度为(Len)的后缀时,([1,N])中前缀为(x)的数的数量。

    Code

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    
    #define RG register int
    #define LL long long
    
    LL N,K;
    
    inline LL f(LL x,LL Len){
        LL L=0,R,Res=0;
        if(x&1) R=(1LL<<Len)-1;
        else R=(1LL<<(Len+1))-1;
        x<<=Len;
        if(x>N) return 0;
        while(L<=R){
            LL mid=(L+R)>>1;
            if(x+mid<=N){Res=mid+1;L=mid+1;}
            else R=mid-1;
        }
        return Res;
    }
    
    bool Judge(LL x){
        LL temp=x,Res=0,Len=0;
        while(temp<=N){Res+=f(x,Len);++Len;temp<<=1;}
        if(Res>=K) return true;
        return false;
    }
    
    inline LL GetLen(LL x){
        LL Len=0;
        while(x){++Len;x>>=1;}
        return Len-1LL;
    }
    
    int main(){
        cin>>N>>K;
        LL Ans=1;
        while(Judge(Ans<<1)) Ans<<=1;
        LL Len=GetLen(Ans);
        for(RG i=Len-1;i>=0;--i)
            if(Judge(Ans+(1LL<<i))) Ans+=(1LL<<i);
        cout<<Ans<<endl;
        return 0;
    }
    
  • 相关阅读:
    删除某个目录下面指定名字的文件夹的命令
    ubuntu 12.04 下面安装vmware workstation 8.0.4
    最近一段时间总结
    ejb 学习笔记HelloWorld入门实例
    状态会话bean的session周期与Web上的session周期
    ubuntu做路由器
    Heron and His Triangle 递推 高精度 打表 HDU6222
    洛谷训练赛 A.Misaka Network
    HZNU Training 1 for Zhejiang Provincial Competition 2020 Xeon第三场训练赛
    莫比乌斯反演
  • 原文地址:https://www.cnblogs.com/AEMShana/p/12431440.html
Copyright © 2011-2022 走看看