poj 3252 Round Numbers(数学)

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

题意:一个数写成二进制,0不少于1就是round number,求给定区间内round number的个数。

分析:显然第一步转化为0到n的round number个数。。设n写成二进制有len位,第一位取0时,后面只要满足0的个数要求就行了,不用考虑是否比n大。。可以先预处理一下长度不大于len的round number个数,记做t[len],t[len]=t[len-1]+∑C(len-1  k) , (k=0,1,...,len/2-1)。

然后第一位取1时,往后是0的位只能取0,遇到第一个1时,再分情况考虑这一位为1和为0,然后考虑还需要多少位,往下递归即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=35;
 6 int C[maxn][maxn],sum[maxn][maxn][maxn],t[maxn];
 7 int start,finish;
 8 void CalC(){
 9     for(int i=1;i<maxn;i++)
10         C[i][0]=C[i][i]=1;
11     for(int i=2;i<maxn;i++){
12         for(int j=1;j<i;j++){
13             C[i][j]=C[i-1][j]+C[i-1][j-1];
14         }
15     }
16     for(int i=0;i<maxn;i++){
17         for(int s=0;s<=i;s++){
18             sum[i][s][s]=C[i][s];
19             for(int t=s+1;t<=i;t++){
20                 sum[i][s][t]=sum[i][s][t-1]+C[i][t];
21             }
22         }
23     }
24 }
25 void CalT(){
26     t[1]=1;
27     for(int i=2;i<maxn;i++){
28         t[i]=t[i-1]+sum[i-1][0][(i-2)/2];
29     }
30 }
31 int f(int n,int c,int len){
32     if(c==0)return 1;
33     if(c>=len)return n+1;
34     int t=len-1;
35     while(t>=0&&(n&(1<<(t-1)))==0){
36         t--;
37     }
38     return f(n-(1<<(len-1)),c-1,t)+sum[len-1][0][c];
39 }
40 int solve(int n){
41     if(n==0)return 1;
42     int k=1<<30,len=31;
43     while((k&n)==0){
44         k>>=1;len--;
45     }
46     int l=len-1;
47     while(l>=0&&(n&(1<<(l-1)))==0){
48         l--;
49     }
50     return t[len-1]+f(n-(1<<(len-1)),(len-2)/2,l);
51 }
52 //bool Is_round(int n){
53 //    int k=1,a=0,b=0;
54 //    while(k<=n){
55 //        if(k&n)a++;
56 //        else b++;
57 //        k<<=1;
58 //    }
59 //    if(a<=b)return true;
60 //    return false;
61 //}
62 //int test(int n){
63 //    int count=0;
64 //    for(int i=1;i<=n;i++){
65 //        if(Is_round(i))count++;
66 //    }
67 //    return count+1;
68 //}
69 int main(){
70     CalC();
71     CalT();
72     int n;
73 //    while(cin>>n){
74 //        cout<<solve(n)<<' '<<test(n)<<endl;
75 //    }
76     cin>>start>>finish;
77     cout<<solve(finish)-solve(start-1)<<endl;
78     return 0;
79 }

 

posted @ 2017-08-03 23:02  7391_KID  阅读(101)  评论(0编辑  收藏  举报