POJ3252-Round Numbers 数学

题目链接:http://poj.org/problem?id=3252

题目大意:

  输入两个十进制正整数a和b,求闭区间 [a ,b] 内有多少个Round number

  所谓的Round Number就是把一个十进制数转换为一个无符号二进制数,若该二进制数中0的个数大于等于1的个数,则它就是一个Round Number

  规定输入范围: 1<= a <b<=2E

/*

一开始错在计算组合数!!!正解是利用杨辉三角来算!!
另外对于star=1的情况下也需要特判一下子
思路是算出【0,star】和【0,fini】的round number(以下简称rn)个数,后者减去前者+1*【star是rn】(艾弗森约定)
要计算【0,a】的rn个数,设a的二进制表示长度为lena,那么先打表f[]给出二进制表示数长度为1-->lena-1的这些数的rn。
再计算长度为lena的,但是比a小的这些数里头有哪些是rn呢?
计算同长度的rn的思路是:从高位到低位将a的二进制表示中的1(除最高位)逐次变为0,更低位的则在满足rn条件的前提下随便进行排列,得到的数一定是小于a的rn
当然某一位变完了以后又会变回来的啊。这部分详见fun();

*/

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 using namespace std;
  6 #define MAX 35
  7 #define unsigned int long long
  8 long long f[MAX];
  9 long long  star,fini;
 10 char str0[35],str1[35];
 11 long long c[40][40];
 12 void   d2b(long long d, char *str)//十进制转成二进制!
 13 {
 14     int nStart = -1, i = 0;
 15     for (i=0; i<32; i++)
 16     {
 17         bool bOne = (0 != (d & (1 << (32-i-1) )));
 18         if (bOne && nStart < 0)
 19         {
 20             nStart = i;
 21         }
 22         if(nStart>=0)
 23         {
 24             str[i - nStart] = bOne ? '1' : '0';
 25         }
 26     }
 27     str[i - nStart] = '\0';
 28     return ;
 29 }
 30 
 31 long long pow3( long long a, long long b )//快速幂
 32 {
 33     long long r = 1, base = a;
 34     while( b != 0 )
 35     {
 36         if( b & 1 )
 37         r *= base;
 38         base *= base;
 39         b >>= 1;
 40     }
 41     return r;
 42 }
 43 
 44 void play_table(void)//计算组合数的!
 45 {
 46     for(int i=0;i<=35;i++)
 47         for(int j=0;j<=i;j++)
 48             if(!j || i==j)
 49                 c[i][j]=1;
 50             else
 51                 c[i][j]=c[i-1][j-1]+c[i-1][j];
 52     return;
 53 }
 54 
 55 void  Cf()//计算f[]
 56 {
 57     f[1]=1;
 58     for(int i=2;i<MAX;i++){
 59         int k=i/2;
 60         if(i%2)
 61             f[i]=(pow3(2,2*k)-c[2*k][k])/2;
 62         else
 63             f[i]=pow3(4,k-1);
 64     }
 65 }
 66 
 67 long long  fun(char ss[35])
 68 {
 69     int sum0=0;//ss中0的个数。
 70     int len=strlen(ss);
 71     long long ans=0;
 72     for(int i=1;i<len;i++)
 73         ans+=f[i];
 74     for(int k=1;k<len;k++)
 75     {
 76         if(ss[k]=='0')
 77             sum0++;
 78         else
 79         {
 80             int t0=ceil(1.0*len/2)-sum0-1;//至少需要的0个数
 81             int s=len-k-1;//剩下的可变位数
 82             if(t0<=0)
 83                 ans+=pow3(2,s);
 84             else
 85                 if(t0<=s)
 86                     for(int i=t0;i<=s;i++)
 87                         ans+=c[s][i];//(s,i);
 88         }
 89     }
 90     if(sum0>=ceil(1.0*len/2))//相当于本身
 91         ans++;
 92     return ans;
 93 }
 94 
 95 bool ok(char s[35])
 96 {
 97     int sum0=0;
 98     int len=strlen(s);
 99     if(strcmp(s,"1")==0)
100         return 0;
101     for(int i=1;i<len;i++)
102         if(s[i]=='0')
103             sum0++;
104     if(sum0>=ceil(1.0*len/2))
105         return 1;
106     return 0;
107 }
108 
109 int  main()
110 {
111     play_table();
112     Cf();
113     while(cin>>star>>fini)
114     {
115         d2b(star,str0);
116         d2b(fini,str1);
117         if(star==1) ans0++;//对1进行特判
118         if(ok(str0))
119             cout<<fun(str1)-fun(str0)+1<<endl;
120         else
121             cout<<fun(str1)-fun(str0)<<endl;
122     }
123     return 0;
124 }

 

posted on 2013-08-05 21:34  GyyZyp  阅读(232)  评论(0编辑  收藏  举报

导航