poj 3252 Round Numbers 组合数学

来源:互联网 发布:mac网络恢复系统 编辑:程序博客网 时间:2024/04/30 13:31

题目链接:poj 3252

        找出给定范围内,二进制0大于1的数的数量

        组合数学,结果为sum(r)-sum(l-1),求sum通过组合数找出小于当前数长度的所有round数,对于当前长度遇1置0后统计之后的所有数,最后特判一下本身即可。

/*********************************************************************  FileName: 3252.cpp  Author: kojimai  Created Time: 2014年08月06日 星期三 15时22分54秒*********************************************************************///找出给定范围内二进制数0数目大于1的有多少个/*sum(i)表示从1到i有多少个round数,结果即为sum(r)-sum(l-1)求sum(i):首先统计所有二进制长度比i小的round数然后对找出i的二进制数,从高位到低位扫一遍遇到1则该位置0统计后面剩余可能的round数最后判断一下这个数本身是否是round数即可*/#include<cmath>#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int C[33][33];void init(){C[0][0]=1;for(int i=1;i<=31;i++){C[0][i]=C[i][i]=1;}for(int i=2;i<=31;i++){for(int j=1;j<i;j++){C[j][i]=C[j][i-1]+C[j-1][i-1];}}return;}int a[33];int turn(int num)//转化为二进制数{int now=0;while(num){a[now]=num%2;now++;num/=2;}return now;}int Cnt(int len,int l1,int l2)//总长度为len,已经有l1个1,l2个0{int ret=0;for(int i=0;i+l1<=len/2;i++)ret+=C[i][len-l1-l2];return ret;}int solve(int num){int ans=0,cnt1=1,cnt0=0;int len=turn(num);for(int i=2;i<=len-1;i++)//找出二进制长度比num小的二进制数{for(int j=1;j<=(i/2);j++)//利用组合数求出1的数目从1到i/2的所有的情况ans+=C[j-1][i-1];}//cout<<" ans="<<ans<<endl;for(int i=len-2;i>=0;i--){if(a[i]==1){ans+=Cnt(len,cnt1,cnt0+1);//若当前位为1,则该位置0之后统计之后的所有数cnt1++;//cout<<"  ans="<<ans<<endl;}elsecnt0++;}if(cnt1<=cnt0)//判断这个数本身ans++;return ans;}int main(){init();int start,end;scanf("%d%d",&start,&end);cout<<solve(end)-solve(start-1)<<endl;        return 0;}


0 0
原创粉丝点击