这是一个数学题。
这就是我一开始给他的定义。
题目中的故事都是无关的,题目要求如下:
给出Round Number定义,给出Start,Finish两个数。求在[Start ,Finish]这个区间内的Round Number 有多少个。
其中Round Number是这样定义的:将当前数其转化为二进制,如果0的个数大于等于1的个数,当前数就是Round Number。
思路:
1、求[Start ,Finish]这个区间的Round Number 的数量可以转化为求[0,Start -1]和[0,Finish]这两个区间中Round Number的数量,然后相减得出。
2、然后对于每一个某个数到0的区间来说,可以针对这个数来处理出共有多少个Round Number。这就是一个函数就可以解决的问题了。
3、对于这个函数来说,处理的这个数要先转换成二进制存贮。具体方法看自己,什么方法用的顺手用什么方法。
我们假设转化成二进制后长度为6,我们要分两部分来处理。
(1)、第一部分是0到五位,需要枚举位数处理。
对于五位长的数来说,第一位只能是1,剩下四位可以取四个0、三个0才能是Round Number,两个0就不行了。也就是说需要加C(4,4),C(4,3).
对于四位长的数来说,第一位只能是1,剩下的三位可以取三个0,两个0。一个0就不行了。也就是说需要加C(3,3),C(3,2).
以此类推,直到计算完成为止。
(2)、第二部分是当六位数的时候。
第一位一定是1是不能改变的,后面跟着的连续的几个零也是不能改变的。所以只能在第二个1开始处理。
将每一次遇到的1视为0,计算从第一位到当前位共有多少个1多少个0,然后计算此位之后有多少个1,多少个0就能构成Round Number,用组合数计算。
注意:如果当前数转化为二进制后发现为Round Number,计数器需要加一。
下面是我的代码:
#include <stdio.h>
int c[35][35]= {0},len=0;
char s[35];
int po(int a,int b) //平方函数
{
int sum=1;
while(b>0)
{
sum*=a;
b--;
}
return sum;
}
int Rn(int num) //计算从0到x的round number 的个数
{
if(!num)
{
return 0;
}
len=0;
int cnt=0,One=0,Zero=0;
while(num)//处理成二进制
{
s[len]=(num%2)+'0';
if(s[len]=='1')
{
One++;
}
else
{
Zero++;
}
num/=2;
len++;
}
if(Zero>=One)//如果当前数为Round Number 则计数器加一
{
cnt++;
}
for (int i = 1; i < len - 1; i++)
{
for (int j = i / 2 + 1; j <= i; j++)
{
cnt += c[i][j];
}
}
int i=len-1;
One =1;
Zero=0;
while(i>0)
{
while(s[i-1]!='1'&&i>0)
{
Zero++;
i--;
}
if(i<=0)
{
break;
}
for(int j=(len+1)/2-(Zero+1); j<=i-1; j++)
{
cnt+=c[i-1][j];
}
One++;
i--;
}
return cnt;
}
void S()//C(n,m)初始化
{
int i,j;
for(i=0; i<33; 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];
}
}
}
}
int main()
{
int a,b;
S();
while(~scanf("%d%d",&a,&b))
{
printf("%d\n",Rn(b)-Rn(a-1));
}
return 0;
}