您的位置:首页 > 其它

poj_3252 Round Numbers(组合数学)

2016-11-28 12:15 477 查看
Round Numbers

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 12617 Accepted: 4841
Description

The cows, as you know, have no fingers or thumbs and thus are unable to play Scissors, Paper, Stone' (also known as 'Rock, Paper, Scissors', 'Ro, Sham, Bo', and a host of other names) in order to make arbitrary decisions such as who gets to be milked first.
They can't even flip a coin because it's so hard to toss using hooves.

They have thus resorted to "round number" matching. The first cow picks an integer less than two billion. The second cow does the same. If the numbers are both "round numbers", the first cow wins,

otherwise the second cow wins.

A positive integer N is said to be a "round number" if the binary representation ofN has as many or more zeroes than it has ones. For example, the integer 9, when written in binary form, is 1001. 1001 has two zeroes and two ones; thus,
9 is a round number. The integer 26 is 11010 in binary; since it has two zeroes and three ones, it is not a round number.

Obviously, it takes cows a while to convert numbers to binary, so the winner takes a while to determine. Bessie wants to cheat and thinks she can do that if she knows how many "round numbers" are in a given range.

Help her by writing a program that tells how many round numbers appear in the inclusive range given by the input (1 ≤Start <
Finish ≤ 2,000,000,000).

Input
Line 1: Two space-separated integers, respectively
Start and Finish.
Output
Line 1: A single integer that is the count of round numbers in the inclusive rangeStart..Finish
Sample Input
2 12

Sample Output
6


找两个正整数之间的 二进制表示 中 0的个数 大于等于 1的个数 的 数字的个数。

组合数学。先分别求出小于其中一个正整数的整数中符合条件的个数,再作减法。

比如求小于二进制表示为101101100的round number个数。

101101100的位数为9


可以把小于101101100的正整数分为位数小于9,和等于9两种情况。

小于9的话,有位数为1,2,3,4,5,6,7,8,9九种情况。

位数为1即1,不满足题意。

位数为5的话,第一位一定为1,所以后面四位中的0的个数至少为3才是round number,可得C(4, 3) + C(4, 4)。

以此类推。


位数等于9时,可以遍历一遍a[9] = {1,0,1,1,0,1,1,0,0},当a[i]为1时做处理。


/ 101101100

/ 101101*** \ 1011010** C(2,2)

/ 1011***** \ 101100*** C(3,2)+C(3,3)

/ 101****** \ 1010***** C(5,3)+C(5,4)+C(5,5)

10 \ 100****** (*号区域至少需要3个0)得 C(6,3)+C(6,4)+C(6,5)+C(6,6)


把两个情况加起来就得到了小于101101100的正整数中round number的个数。


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <stack>
#include <bitset>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <algorithm>
#define FOP freopen("data.txt","r",stdin)
#define FOP2 freopen("data1.txt","w",stdout)
#define inf 0x3f3f3f3f
#define maxn 1000010
#define mod 1000000007
#define PI acos(-1.0)
#define LL long long
using namespace std;

int C[50][50];
int s, e;
int sb[50], eb[50];
int sc, ec;

int solve(int* a, int len)
{
int ans = 0;

for(int i = len - 1; i >= 1; i--)
{
int l = i-1;
int mi = i + 1 >> 1;
for(int j = mi; j <= l; j++) ans += C[l][j];
}

int n0 = 0, n1 = 1;
int mi0 = len+1 >> 1;
for(int i = 2; i <= len; i++)
{
if(a[i]&1) n1++;
else n0++;
if(a[i] & 1)
{
int mi = mi0 - n0 - 1;
for(int j = mi; j <= len-i; j++) ans += C[len-i][j];
}
}
if(n0 >= n1) ans++;
return ans;
}

int main()
{
//FOP;
C[0][0] = 1;
for(int i = 1; i <= 100; 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]) % mod;
}

while(~scanf("%d%d", &s, &e))
{
sc = 1, ec = 1;
s--;
int t = s;
while(t)
{
sb[sc++] = t&1;
t >>= 1;
}
sc--;
for(int i = 1; i <= sc/2; i++) swap(sb[i], sb[sc-i+1]);
t = e;
while(t)
{
eb[ec++] = t&1;
t >>= 1;
}
ec--;
for(int i = 1; i <= ec/2; i++) swap(eb[i], eb[ec-i+1]);
int ans1 = solve(sb, sc);
int ans2 = solve(eb, ec);
printf("%d\n", ans2 - ans1);

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: