poj3252 Round Numbers

Round Numbers
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 11850 Accepted: 4461

Description

The cows, as you know, have no fingers or thumbs(拇指) and thus are unable to play Scissors, Paper, Stone' (also known as 'Rock, Paper, Scissors', 'Ro, Sham, Bo', and a host of other names) in order to makearbitrary(任意的) decisions such as who gets to be milked first. They can't even flip(弹) a coin because it's so hard to toss(投掷) using hooves(蹄).

They have thus resorted(求助) to "round number" matching. The first cow picks an integer(整数) less than two billion. The second cow does the same. If the numbers are both "round numbers", the first cow wins,
otherwise the second cow wins.

A positive integer N is said to be a "round number" if the binary(二进制的) representation(代表) of N has as many or more zeroes than it has ones. For example, the integer(整数) 9, when written in binary form, is 1001. 1001 has two zeroes and two ones; thus, 9 is a round number. The integer 26 is 11010 in binary; since it has two zeroes and three ones, it is not a round number.

Obviously, it takes cows a while to convert(转变) numbers to binary, so the winner takes a while to determine. Bessie wants to cheat and thinks she can do that if she knows how many "round numbers" are in a given range.

Help her by writing a program that tells how many round numbers appear in the inclusive(包括的) range given by the input(投入) (1 ≤ Start < Finish ≤ 2,000,000,000).

Input

Line 1: Two space-separated integers,  respectively (分别的)  Start and  Finish.

Output

Line 1: A single integer that is the count of round numbers in the inclusive range  Start.. Finish

Sample Input

2 12

Sample Output

6

今天踏入了组合数学的领域,QAQ真是虐的不要不要的,不学习前辈的知识根本什么都不知道啊。

这个题就是给你两个数a,b问你从a到b有多少个round number暂且成为RB好了。

RB:转化为二进制数后,0的个数大于等于1的个数的数。

很容易想到就是用组合数学的知识,比如说一个数有l位,那么我们只要从l里面选取大于等于了l/2小于等于l个0就是满足条件的~

首先我们要转化一下思想,它让我们求从a~b的,我们知道直接来求需要判断大小问题很麻烦,我们可以构造函数来求出0~X之间的所有的RB,这样我们只需要分别算出对应的两个函数值相减就可以了,这样就转化成了一个问题!

现在的问题就是怎么求0~X之间的RB呢?我们首先把X转化为二进制数,记长度为l

首先比较好考虑的就是长度小于l的,这样的二进制数肯定比X小,这样我们就可以直接来求:

for(i=1;i<bin[0]-1;++i)         //bin[0]记录的是二进制数的长度l

              for(j=i/2+1;j<=i;++j)

                     sum+=c[i][j];

可以看到,i<len-1 ,之所以减1,是因为这些长度比len小的数,最高位一定是1,那么剩下可供放入数字的位数就要再减少一个了,所以我们至少要选取i/2+1个0才是满足条件的。

这条程序得到的sum


1表示的是二进制数的最高为,而X就是剩余的可以放置的位,qwq前辈就是腻害。

可以想到的就是没有0,这里相当于是从2位起开始考虑的,因为最后要相减,并且0都是有的,所以这里就没必要加了。

然后就是要考虑二进制数的长度和X相同,但是比X小的数了。qwq,这里我们采用从高位到地位搜索的方法:

如果这一位是0,我们的计数器+1,其余不做,处理。

如果这一位是1,我们就把这一位降成0(这样这个数是比X小的),然后依次枚举剩下的i-1位中0的个数就可以了~

int cnt=0;  //从高位向低位搜索过程中出现0的位的个数

       for(i=l[0]-1;i>=1;--i)

              if(l[i])   //当前位为1

                     for(j=(l[0]+1)/2-(cnt+1);j<=i-1;++j)

                            sum+=c[i-1][j];

              else

                     cnt++;


(l[0]+1)/2这里是最少需要的0的个数,(cnt+1)是已经出现了的0的个数,两个相减便是最少还需要的0的个数。

如果最少还需要的0的个数小于0当然是置0,然后依次枚举到i-1个。小于0的话一定要置0,因为从0个里面选0个是有一种方法的(也就是这个i位变成0也是一种可行的解)。

(表示某人写时候的完全没考虑负值呐╮(╯▽╰)╭)

http://www.cnblogs.com/lyy289065406/archive/2011/07/31/2122758.html   诺,qwq这是前辈的

之后就在代码中说吧

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
using namespace std;
const int MAXN=40+10;
const int inf=0x3f3f3f;
int c[MAXN][MAXN];
int l[MAXN];

void getc()//打表计算C[i][j]
{
    int i,j;
    for(i=0;i<=32;++i)
            for(j=0;j<=i;++j)
        {
            if(!j||i==j)c[i][j]=1;
            else
            c[i][j]=c[i-1][j-1]+c[i-1][j];
        }


}

void two(int n)//得到二进制数
{
    l[0]=0;
    while(n)
    {
        l[++l[0]]=n&1;
        n>>=1;
    }
}

int getround(int n)//计算从0~n-1中RN的个数
{
    int i,j;
    int sum=0;
    two(n);
    //先计算长度比n小的
    for(i=1;i<l[0]-1;++i)
    {
        for(j=i/2+1;j<=i;++j)
        {
            sum+=c[i][j];
        }
    }
    //然后计算长度和n一样但是比n小的
    int cnt=0;
    for(i=l[0]-1;i>=1;--i)//这里从高位到低位搜索,最高位肯定是一,所以从l[0]-1开始
    {
        if(l[i])
        {
            j=((l[0]+1)>>1)-(cnt+1);
            if(j<0)j=0;
            for(;j<=i-1;++j)
            {
                sum+=c[i-1][j];
            }
        }
        else cnt++;
    }
    return sum;
}



int main()
{
    int n,m;
    getc();
    scanf("%d%d",&n,&m);
    n=getround(n);
    m=getround(m+1);
    printf("%d\n",m-n);
    return 0;
}

这里我们求出的是小于n的二进制的数,所以伪函数的f(b)-f(a-1)就是上面的f(b+1)-f(a)辣~





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值