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;

 

posted @ 2010-07-28 21:15  勇泽  阅读(451)  评论(0编辑  收藏  举报