牛客网__随机数

链接:https://ac.nowcoder.com/acm/contest/984/F
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

正如你所知,奶牛们没有手指以至于不能玩“石头剪刀布”来任意地决定例如谁先挤奶的顺序。她们甚至也不能通过仍硬币的方式。
所以她们通过"round number"竞赛的方式。第一头牛选取一个整数,小于20亿。第二头牛也这样选取一个整数。如果这两个数都是 "round numbers",那么第一头牛获胜,否则第二头牛获胜。
如果一个正整数N的二进制表示中,0的个数大于或等于1的个数,那么N就被称为"round number" 。例如,整数9,二进制表示是1001,1001 有两个'0'和两个'1'; 因此,9是一个round number。26 的二进制表示是 11010 ; 由于它有2个'0'和3个'1',所以它不是round number。
很明显,奶牛们会花费很大精力去转换进制,从而确定谁是胜者。 Bessie 想要作弊,而且认为只要她能够知道在一个指定区间范围内的"round numbers"个数。
帮助她写一个程序,能够告诉她在一个闭区间中有多少Hround numbers。区间是[start, finish],包含这两个数。 (1 <= Start < Finish <= 2,000,000,000)

输入描述:

Line 1: 两个用空格分开的整数,分别表示Start 和 Finish。

输出描述:

Line 1: Start..Finish范围内round numbers的个数

示例1

输入

复制

2 12

输出

复制

6

说明

2    10  1x0 + 1x1  ROUND
3    11  0x0 + 2x1  NOT round
4   100  2x0 + 1x1  ROUND
5   101  1x0 + 2x1  NOT round
6   110  1x0 + 2x1  NOT round
7   111  0x0 + 3x1  NOT round
8  1000  3x0 + 1x1  ROUND
9  1001  2x0 + 2x1  ROUND
10  1010  2x0 + 2x1  ROUND
11  1011  1x0 + 3x1  NOT round
12  1100  2x0 + 2x1  ROUND

拆成二进制就可以算

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

const int maxn = 2e6+9;
const int mod = 1e9+7;
const int INF = 0x3f3f3f3f;

int C[34][34];

void init(){
    C[0][0]=1;
    for(int i=1;i<=32;i++){
        for(int j=0;j<=i;j++){
            if(j==0){C[i][j]=1;continue;}
            C[i][j]=C[i-1][j-1]+C[i-1][j];
        }
    }
//    for(int i=1;i<=32;i++){
//        for(int j=0;j<=i;j++){
//            cout<<C[i][j]<<" ";
//        }
//        cout<<endl;
//    }
}

int solve(int x){
    int ans=0;
    int a[60];
    int tot=0;
    int y=x;
    while(y){
        a[tot++]=y%2;
        y/=2;
    }
    for(int i=1;i<tot-1;i++){
        for(int j=i/2+1;j<=i;j++){
            ans+=C[i][j];
        }
    }
//    cout<<ans<<endl;
    int zero=0;
    for(int i=tot-2;i>=0;i--){
        if(a[i]==0)zero++;
        else{
            for(int j=(tot+1)/2-zero-1;j<=i;j++){
                ans+=C[i][j];
            }
        }
    }
//    cout<<ans<<endl;
    return ans;
}

int main(){
    init();
    int a,b;
    scanf("%d%d",&a,&b);
    printf("%d\n",solve(b+1)-solve(a));
    return 0;
}








 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值