POJ 3252 Round Numbers
这是一个数学题。
这就是我一开始给他的定义。
题目中的故事都是无关的,题目要求如下:
给出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; }