大神们的题解我一个都没看懂。。。。。。。。。。。

十分的尴尬

题意:算出闭区间内二进制中0的个数大于等于1的个数的数字有多少个

思路:

组合数学(n小于500的时候都可以出解,只不过高精比较麻烦)。

这道题还算比较仁慈。。。

Discuss里面有一段说得挺好的

看完各家算法,尝试独立分析一下: 以sample为例子

[2,12]区间的RoundNumbers(简称RN)个数:Rn[2,12]=Rn[0,12]-Rn[0,1]

即:Rn[start,finish]=Rn[0,finish]-Rn[0,start-1] 所以关键是给定一个X,求出Rn[0,X]

现在假设X=10100100 这个X的二进制总共是8位,任何一个小于8位的二进制都小于X

第一部分,求出长度为[0,7]区间内的二进制是RoundNumber的个数

对于一个长度为Len的二进制(最高位为1),如何求出他的RoundNumbers呢(假设为用R(len)来表达),分为奇数和偶数两种情况

1、奇数情况:在Len=2k+1的情况下,最高位为1,剩下2k位,至少需要k+1为0

用C(m,n)表示排列组合数:从m个位置选出n个位置的方法

R(len)=C(2k,k+1)+C(2k,k+2)+…+C(2k,2k). 由于

A:C(2k,0)+C(2k,1)+…+C(2k,2k)=2^(2k)

B:C(2k,0)=C(2k,2k), C(2k,1)=C(2k,2k-1) ,,C(2k,i)=C(2k,2k-i) 于是 C(2k,0)+C(2k,1)+…+C(2k,2k)

= C(2k,0)+C(2k,1)+…+C(2k,k)+C(2k,k+1)+C(2k,K+2)+…+C(2k,2k)

= 2*R(len)+C(2k,k)

=2^(2k)

所以R(len)=1/2*{2^(2k)-C(2k,k)};

2. 偶数情况 len=2*k,类似可以推到 R(len)=1/2*(2^(2k-1)); 第二部分,对于上面这个长度为8的例子:即X=10100100,首先如果本身是RoundNumbers,第二部分的结果总数+1

第一部分已经将长度小于8的部分求出。现在要求长度=8的RoundNumber数目 长度为8,所以第一个1不可改变

现在到第二个1,如果Y是前缀如100*****的二进制,这个前缀下,后面取0和1必然小于X,已经有2个0,一个1,剩下的5个数字中至少需要2个0,

所以把第二个1改为0:可以有C(5,2)+C(5,3)+C(5,4)+C(5,5)

现在第三个1,也就是前最为101000**,同样求出,至少需要0个0就可,所以有C(2,0)+C(2,1)+C(2,2)个RoundNumbers

。。。

将所有除了第一个1以外的1全部变为0,如上算出有多少个RoundNumbers,结果相加(由于前缀不一样,所以后面不管怎么组合都是唯一的)

将第一部分和第二部分的结果相加,就是最后的结果了。 精度要求方面,用int就可以了:two

billion=20亿<2*1024*1024*1024=2^31,需用31位来表示数组,由于第一位总是1,所以求组合数的时候最多求30,C(30,k),k取值区间是[0,30],因为C(k,i)<2^k,所以结果用int表示就可以

(也有人用数位DP、记忆化搜索什么的。。。。 看个人喜好吧)

G++ AC C++WA 鬼知道为什么。。。

// by SiriusRen
#include <bitset>
#include <cstdio>
#include <algorithm>
using namespace std;
bitset<64>n,m;
int C[35][35];
int N,M,maxn=0,maxm=0,cnt1=1,cnt0=0;
int ans=0;
int main()
{
scanf("%d%d",&N,&M);M++;
for(int i=30;i>=0;i--){
if(M&(1<<i))m[i]=1,maxm=max(maxm,i);
if(N&(1<<i))n[i]=1,maxn=max(maxn,i);
}
for(int i=0;i<=31;i++)C[i][0]=1;
for(int i=1;i<=31;i++)
for(int j=1;j<=i;j++)
C[i][j]=C[i-1][j-1]+C[i-1][j];
for(int i=maxm;i>=0;i--)
for(int j=i-1;2*j>=i;j--)ans+=C[i-1][j];
for(int i=maxm-1;i>=0;i--)
if(m[i]){
for(int j=maxm-cnt0-cnt1;2*j+2*cnt0+1>=maxm;j--)
ans+=C[maxm-cnt0-cnt1][j];
cnt1++;
}
else cnt0++;
cnt1=1;cnt0=0;
for(int i=maxn;i>=0;i--)
for(int j=i-1;2*j>=i;j--)ans-=C[i-1][j];
for(int i=maxn-1;i>=0;i--)
if(n[i]){
for(int j=maxn-cnt0-cnt1;2*j+2*cnt0+1>=maxn;j--)
ans-=C[maxn-cnt0-cnt1][j];
cnt1++;
}
else cnt0++;
printf("%d\n",ans);
}

看到另一份题解里有这样一句话:

组合数学,一跪一天,爽!

表示赞同

POJ 3252 组合数学?的更多相关文章

  1. POJ 3252 (数位DP)

    ###POJ 3252 题目链接 ### 题目大意:给你一段区间 [Start,Finish] ,在这段区间中有多少个数的二进制表示下,0 的个数 大于等于 1 的个数. 分析: 1.很显然是数位DP ...

  2. POJ 3252:Round Numbers

    POJ 3252:Round Numbers Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 10099 Accepted: 36 ...

  3. POJ 3252 Round Numbers 组合数学

    Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 13381   Accepted: 5208 Description The ...

  4. POJ 3252 Round Numbers(组合数学)

    Round Numbers Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10223   Accepted: 3726 De ...

  5. POJ 3252 Round Numbers(组合)

    题目链接:http://poj.org/problem?id=3252 题意: 一个数的二进制表示中0的个数大于等于1的个数则称作Round Numbers.求区间[L,R]内的 Round Numb ...

  6. poj 3252

    http://poj.org/problem?id=3252//自己搞了很长时间...现在刚刚有点明白.. 1 #include <iostream> using namespace st ...

  7. [poj 3252]数位dp前导0的处理

    通过这个题对于数位dp中前导0的处理有了新的认识. 题目链接:http://poj.org/problem?id=3252 //http://poj.org/problem?id=3252 #incl ...

  8. POJ 3252 Round Numbers

     组合数学...(每做一题都是这么艰难) Round Numbers Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 7607 A ...

  9. poj 3252 Round Numbers 【推导·排列组合】

    以sample为例子 [2,12]区间的RoundNumbers(简称RN)个数:Rn[2,12]=Rn[0,12]-Rn[0,1] 即:Rn[start,finish]=Rn[0,finish]-R ...

随机推荐

  1. VTK+MFC 系列教程 非常强大

    虽然QT才是王道!MFC的懂一些也是好的. 原文链接:http://blog.csdn.net/www_doling_net/article/details/8939115 之前介绍了基于VTK的单文 ...

  2. mysql组复制集群简介

    mysql组复制集群拓扑: 环境: centos6.5 mysql5.7.19 一.组复制搭建: 配置hosts文件 再三台服务器上分别启动一个mysql实例,共三个. 参考配置文件如下: serve ...

  3. Linux 内核剖解(转)

    Linux 内核剖析(转)  linux内核是一个庞大而复杂的操作系统的核心,不过尽管庞大,但是却采用子系统和分层的概念很好地进行了组织.在本文中,您将探索 Linux 内核的总体结构,并学习一些主要 ...

  4. jsoup解析页面

    package com.java.jsoup; /** * jsoup解析网页 * @author nidegui * @version 2019年4月29日 下午5:12:02 * */ impor ...

  5. Jenkins 部署 PHP 应用

    安装 Jenkins 方式一:docker方式安装 拉取jenkins官方镜像,按照镜像文档启动镜像就可以了 方式二:手动安装 以下所有操作都使用 root 用户进行操作. 在各项目官网,下载 Jav ...

  6. BZOJ 1601: [Usaco2008 Oct]灌水 最小生成树_超级源点

    Description Farmer John已经决定把水灌到他的n(1<=n<=300)块农田,农田被数字1到n标记.把一块土地进行灌水有两种方法,从其他农田饮水,或者这块土地建造水库. ...

  7. Day 11 函数之对象和名称空间与作用域

    函数对象 函数是第一类对象,即函数可以被当做数据处理 函数对象的四大功能 1.引用 x=100 y=x def func() pass f=func print(f) #打印结果 #<funct ...

  8. Selenium 安装与配置及webdriver的API与定位元素

    1. selenium安装命令行 C:\Users\wu>cd /d E:\soft\python3.6\Scripts E:\soft\python3.6\Scripts>pip3 in ...

  9. UVA-11806 Cheerleaders 计数问题 容斥定理

    题目链接:https://cn.vjudge.net/problem/UVA-11806 题意 在一个mn的矩形网格里放k个石子,问有多少方法. 每个格子只能放一个石头,每个石头都要放,且第一行.最后 ...

  10. [luogu4310] 绝世好题 (递推)

    传送门 题目描述 给定一个长度为n的数列ai,求ai的子序列bi的最长长度,满足bi&bi-1!=0(2<=i<=len). 输入输出格式 输入格式: 输入文件共2行. 第一行包括 ...