POJ 3252 Round Numbers(组合计数)

转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents           by---cxlove

题目:一个数转化成二进制之后,0的个数大于等于1的为round数,问一个区间内有多少round数。

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

有点像是数位DP的题目。

转化成二进制后只有01两种情况,我们可以直接统计。

我们统计比N小的round数有多少。

对于长度比N小的数,比较简单,如果长度为L,那么高位肯定是1,然后枚举0的个数,利用组合数就能解决。

然后是长度和N一样,但是比N小的。

我们从高位开始枚举,如果出现1,则把这位看作0,那么枚举之后的低位,肯定是比原数小的。

依次下去,注意统计好高位已经出现的0,1个数。

#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<vector>
#define C    240
#define TIME 10
#define inf 1<<25
#define LL long long
using namespace std;
int c[35][35];
void Init(){
    for(int i=0;i<33;i++){
        c[i][0]=c[i][i]=1;
        for(int j=1;j<i;j++)
            c[i][j]=c[i-1][j]+c[i-1][j-1];
    }
}
int slove(int n){
    int len=0,bit[35];
    while(n){
        bit[++len]=n%2;
        n/=2;
    }
    int sum=0;
    for(int i=1;i<len;i++)
        for(int j=(i+1)/2;j<i;j++)
            sum+=c[i-1][j];
    int one=1,zero=0;
    for(int i=len-1;i;i--){
        if(bit[i]){
            //如果这位是1,则如果是0,枚举低位,肯定比原数小
            zero++;
            for(int j=max(0,(len+1)/2-zero);j<i;j++)
                sum+=c[i-1][j];
            //统计结束后,要恢复
            zero--;
            one++;
        }
        else
            zero++;
    }
    return sum;
}
int main(){
    int l,r;
    Init();
    while(cin>>l>>r)
        cout<<slove(r+1)-slove(l)<<endl;
    return 0;
}


你可能感兴趣的:(c,Numbers)