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 }

 

转载于:https://www.cnblogs.com/7391-KID/p/7282581.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值