POJ 3252

本文深入探讨了Round Numbers的定义及特点,并提供了一种高效的算法来计算特定区间内Round Numbers的数量。通过对不同二进制位数的讨论,文章详细介绍了如何利用组合数学原理解决该问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Round Numbers就是一个表示成二进制的时候01多或者相等的正数,注意是正数,所以0就肯定不是了。

 题目是给定一个区间,问在这个区间上的Round Numbers有多少个?

     

比如 N = 12, 则他的长度是4, 那么位数比4小的一定是比N小的Round Numbers

    当len = 3 , 则 num = C(2,2) 因为此时第一位必须是1

同理 当len = 2.  Num = C(1,1)

    当 len = 3  num = 0

当长度相同的时候

当 len = 4 此时round number 必须必1100小, 我们就从1入手, 当然了首位不能动

然后我们把以后的1一次变为0就可以保证 一定比N小, 当第二个1变为零时 即 前缀位10~的数, 又要满足条件 num = C(21) + C(22) 奏是这样

  

如果二进制N位数为奇数 设N = 2*k + 1, 则满足条件的比N -1Round Numbers C(2K, K+1) ~ C(2K, 2K) 

   因为 C(N,0) + C(N, 1) + C(N,2) + ....+C(N,N) = 2^(N); && C(N, M) = C(N, N-M);

  2^(2k) = C(2k,0)+C(2k,1)+...+C(2k,k-1) +C(2k,k)+C(2k,k+1)+C(2k,K+2)+...+C(2k,2k)

       = C(2k,2k)+C(2k,2k-1)+...+C(2k,k+1) +C(2k,k)+C(2k,k+1)+C(2k,K+2)+...+C(2k,2k)

       =2*num + C(2k,k);  

 Num = (2^(2k) - C(2k,k))/2;

 同理 当N = 2*k 时 则满足条件的比N -1Round Numbers C(2K-1, K) ~ C(2K,-1 2K-1) 

 2^(2k-1)=C(2k-1,0)+C(2k-1,1)+...+C(2k-1,k-1)+C(2k-1,k)+C(2k-1,K+1)+...+C(2k-1,2k-1)

        =C(2k-1,2k-1)+C(2k-1,2k-2)+...+C(2k-1,k)+C(2k-1,k)+C(2k-1,K+1)+...+C(2k-1,2k-1)

        =2*num 

Num = 2^(2k-1)/2;

 

 

#include <iostream>

#include <string.h>

#include <stdio.h>

#include <stdlib.h>

 

using namespace std;

int bit[33];

int dp[32][32];

 

void init()

{

    memset(dp, 0, sizeof(dp));

   //dp[i][j] 长度为 i, 包含 个 可以都为零

    for( int i = 0; i <= 31; i++)

     dp[i][0] = dp[i][i] =  1;

 

    for(int i = 1; i <= 31; i++)

      for(int j = 1; j < i; j++)

        dp[i][j] = dp[i-1][j-1] + dp[i-1][j];

 

    return ;

}

 

 

void getbit( int x)

{

    bit[0] = 0;

    while(x)

    {

        bit[++bit[0]] = x % 2;

        x/=2;

    }

    return ;

}

 

 

int solve(int n)

{

    getbit(n);

    int sum = 0;

 

    //统计比n长度小的ROUND NUMBER (让第一位是1)

    for(int i = 1; i < bit[0]; i++)

      {//这时候就体现出来dp[i][j]为什么允许都是零了

       for( int j = i - 1; 2*j >= i; j--)

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

      }

    //统计跟n长度相等,值比n小的ROUNDE NUMBER

    int znum = 0;

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

    {

        if(bit[i])

        {

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值