cf1271E——数学找规律,二分套二分

哎,规律就是难看出来

/*
二分判y是否可行,judge函数里:
    找规律可以发现:
    y是奇数时
        第0层:y 
        第一层:2y,2y+1
        第二层:4y,4y+1,4y+2,4y+3
        第三层:8y,8y+1,8y+2,8y+3,8y+4,8y+5,8y+6,8y+7
            ...
        第k层:[2^k*y,2^k*y+2^k-1] 
    
    y是偶数时
        第0层:y,y+1 
        第一层:2y,2y+1,2y+2,2y+3 
        第二层:4y,4y+1,4y+2,4y+3,4y+4,4y+5,4y+6,4y+7
        第三层:8y,8y+1,8y+2,8y+3,8y+4,8y+5,8y+6,8y+7,8y+8,8y+9,8y+10,8y+11,8y+12,8y+13,8y+14,8y+15 
            ...
        第k层:[2^k*y,2^k*y+2^(k+1)-1] 
    
然后统计一下即可
特别注意,对起点是奇数偶数两种情况要特别注意一下,分开来进行二分 

*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long

ll n,K;

ll Pow(ll a,ll b){
    ll res=1;
    while(b){
        if(b%2)res=res*a;
        b>>=1;a=a*a;
    }
    return res;
}
ll judge(ll y){
    ll sum=0,k=0;
    if(y%2==0){//偶数 
        while(Pow(2,k)*y+Pow(2,k+1)-1<=n){
            sum+=Pow(2,k+1);
            k++;
        }
        sum+=max(0ll,n-Pow(2,k)*y+1);
    }
    else {
        while(Pow(2,k)*y+Pow(2,k)-1<=n){
            sum+=Pow(2,k);
            k++;
        }
        sum+=max(0ll,n-Pow(2,k)*y+1); 
    }
    if(sum>=K)return 1;
    return 0;
}

int main(){
    cin>>n>>K;
    ll L=0,R=(n-1)/2,mid,ans1=1;
    while(L<=R){
        mid=L+R>>1;
        if(judge(mid*2+1))
            ans1=mid*2+1,L=mid+1;
        else R=mid-1;
    }
    
    L=1,R=n/2;
    ll ans2=1;
    while(L<=R){
        mid=L+R>>1;
        if(judge(mid*2))
            ans2=mid*2,L=mid+1;
        else R=mid-1;
    }
    cout<<max(ans1,ans2)<<'\n';
}

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/12115002.html
今日推荐