• Round Numbers /// 组合计数 oj21455


    题目大意:

    给定a,b

    输出[a,b]的闭区间中round number的数量

    所谓round就是一个数在二进制下0的个数大于等于1的个数

    0的个数>=1的个数 也就是1的个数<=0的个数

    那么 l 长度中, 1的个数num = l / 2 个,如:l=4 num=2, l=5 num=2

    而当二进制长度为 l 时,首位肯定为1

    那么应在剩下的 l-1 位中 选出 0 到 l / 2 - 1 个位置为1的情况

    递推出31内的组合数就够了 因为 2^31 > 2e9

    找到a,b二进制的位数 L,R

    直接计算 L位 到 R-1位 的所有数量sum

    L位中 比a小的 应该从sum中删去

    R位中 比b小的 应该加进sum中

    如:二进制同样位数下 比 1010100 小的,l=7 l/2=3

    (为什么不从第一个1开始 后面会说)

    从第二个1开始 1010000 要比它小 应该将1置为0

    即100_ _ _ _ 这样就是在之后的4个位置中选出 3-(2-1) 个1

    (最多3个1 已经存在2个 将当前位置为0 那么-1)

    再到第三个1的情况 1010100 要比它小 应该将1置为0

    即10100_ _ 这样就是在之后的2个位置中选出 3-(3-1)个1

    从第一个1开始是不能将其置为0的 所以直接从第二个开始

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    int bi[35];
    int getNum(int x) {
        int c=0;
        while(x) {
            bi[++c]=x&1;
            x >>= 1;
        }
        return c;
    }
    ll C[35][35];
    void init() {
        C[0][0]=C[1][0]=C[1][1]=1LL;
        for(int i=2;i<=35;i++) {
            C[i][0]=C[i][i]=1LL;
            for(int j=1;j<i;j++)
                C[i][j]=C[i-1][j-1]+C[i-1][j];
        }
    }
    int main()
    {
        ll a,b;
        init();
        while(~scanf("%lld%lld",&a,&b)) {
            ll ans=0;
            int L=getNum(a), c=1; // 二进制位数
            for(int i=L-1;i>=1;i--)
                if(bi[i]) { c++;
                    for(int j=0;j<=L/2-(c-1);j++)
                        ans-=C[i-1][j]; /// 减去L位中比a小的
                }
            int R=getNum(b); c=1;
            for(int i=R-1;i>=1;i--)
                if(bi[i]) { c++;
                    for(int j=0;j<=R/2-(c-1);j++)
                        ans+=C[i-1][j]; /// 加上R位中比b小的
                }
    
            for(int i=L;i<R;i++) { /// 加上L位到R-1位的个数
                for(int j=0;j<i/2;j++)
                    ans+=C[i-1][j];
            }
            if(c<=R/2) ans++; // 判断b是不是not round
            // a不需要判断 因为包含在L位中
    
            printf("%lld
    ",ans);
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    系列之前端:从重复造轮子说起
    Asp.Net Core基于JWT认证的数据接口网关Demo
    通过编写一个简单的日志类库来加深了解C#的文件访问控制
    .net core 的图片处理及二维码的生成及解析
    svmtrain和svmpredict简介
    svm小问题
    SVM (support vector machine)
    ubuntu在windows下的wubi安装
    ubuntu在windows下的wubi安装
    [转]无需看到你的脸就能认出你——实现Beyond Frontal Faces: Improving Person Recognition Using Multiple Cues
  • 原文地址:https://www.cnblogs.com/zquzjx/p/9680497.html
Copyright © 2020-2023  润新知