Round Numbers--POJ 3252

1、题目类型:组合数学、数论。

2、解题思路:题意,给出两个数a和b,求出[a,b]之间,有多少个数为round number。round number的定义:其二进制数中0的数量大于或等于1。

3、注意事项:右移过程,在匹配1成功时注意怎样取组合数,以及组合数结束的条件。

4、实现方法:

  
    
#include < iostream >
#include
< cmath >
using namespace std;




// 计算组合m组中的n组
__int64 C( int m, int n)
{
__int64 r
= 1 ;
int h = (m - n) < n ? (m - n):n;
for ( int i = 1 ;i <= h;i ++ )
{
r
*= m;
r
/= i;
m
-- ;
}
return r;
}

void SetTable()
{
Arr[
1 ] = 0 ;
for ( i = 2 ;i <= 31 ;i ++ )
for ( k = (i - 1 ) / 2 + 1 ;k <= i - 1 ;k ++ )
Arr[i]
+= C(i - 1 ,k);
}

int Len( int n)
{
return log(n * 1.0 ) / log( 2.0 ) + 1 ;
}

__int64 Fun(
int n)
{
if (n == 0 )
return 0 ;
int zero = 0 ,one = 1 ,rightzero,len = Len(n);
__int64 cnt
= 0 ;
memset(flag,
0 , sizeof (flag));
// 累加Len(n)之前的和
for (i = 1 ;i < len;i ++ )
cnt
+= Arr[i];
// 确定n的那些位为1
for (i = 0 ;i < len;i ++ )
{
if ((n >> i) & 1 )
flag[i
+ 1 ] = true ;
else
flag[i
+ 1 ] = false ;
}
for (i = len - 1 ;i > 0 ;i -- )
{
// n为偶数
if (len % 2 == 0 )
{
rightzero
= len / 2 ;
if (flag[i])
{
++ one;
for ( k = rightzero - zero - 1 ;k < i;k ++ )
{
if (k >= 0 )
cnt
+= C(i - 1 ,k);
}
}
else
++ zero;

}
// n为奇数
else
{
rightzero
= (len + 1 ) / 2 ;
if (flag[i])
{
++ one;
for ( k = rightzero - zero - 1 ;k < i;k ++ )
{
if (k >= 0 )
cnt
+= C(i - 1 ,k);
}
}
else
++ zero;
}
}
zero
= 0 ;one = 0 ;
// 判断n自身是不是Round Numbers
for (i = 1 ;i <= len;i ++ )
{
if (flag[i])
one
++ ;
else
zero
++ ;
}
if (zero >= one)
cnt
++ ;
return cnt;
}

int main()
{
int start,finish;
SetTable();
scanf(
" %d%d " , & start, & finish);
ans
= Fun(finish) - Fun(start - 1 );
printf(
" %I64d\n " ,ans);
return 0 ;
}
int i,k,Arr[32];
__int64 ans;
bool flag[32],isOK;

 

你可能感兴趣的:(number)