POJ3252 Round Numbers(不重复全排列)
2024-08-29 08:40:40
题目问区间有多少个数字的二进制0的个数大于等于1的个数。
用数学方法求出0到n区间的合法个数,然后用类似数位DP的统计思想。
我大概是这么求的,确定前缀的0和1,然后后面就是若干个0和若干个1的不重复全排列数。。
写得挺痛苦的。。另外A[i][j]表示i个0和j个1的不重复全排列数,即A[i][j]=(i+j)!/i!/j!,这个可以从A[i-1][j]或A[i][j-1]求出来,这样就不用担心乘法溢出了。
#include<cstdio>
#include<cstring>
using namespace std;
long long d[][];
long long cnt(int zero,int one,int len){
long long res=;
for(int i=; i<=len; ++i){
int j=len-i;
if(i+zero<j+one) continue;
res+=d[i][j];
}
return res;
}
long long calu(int a){
int len=;
while(len!=- && ((a>>len)&)==) --len;
if(len==-) return ;
long long res=;
for(int i=; i<len; ++i){
res+=cnt(,,i);
}
int zero=,one=;
for(int i=len-; i>=; --i){
if((a>>i)&){
res+=cnt(zero+,one,i);
++one;
}else{
++zero;
}
}
zero=; one=;
for(int i=; i<=len; ++i){
if((a>>i)&) ++one;
else ++zero;
}
return res+(zero>=one);
}
int main(){
d[][]=;
for(int i=; i<; ++i){
for(int j=; j<; ++j){
d[i+][j]=d[i][j]*(i+j+)/(i+);
d[i][j+]=d[i][j]*(i+j+)/(j+);
}
}
int a,b;
while(~scanf("%d%d",&a,&b)){
printf("%lld\n",calu(b)-calu(a-));
}
return ;
}
最新文章
- strom的使用01
- android基础(六)android的消息处理机制
- bootstrap-table 分页的问题
- CSS Sprite雪碧图应用
- 入门:HTML表单与Java 后台交互(复选框提交)
- Block深入浅出
- .net 邮件批量发送功能源码
- asp.net BulletedList绑定数据及vs2013添加数据库文件
- Makefile常用信息查询页
- Arduino 各种模块篇 RGB LED灯
- DEDECMS整站复制
- JavaScript作用域链和垃圾回收机制
- 【javaFX学习】(二) 面板手册--1
- Javascript中没有块级作用域(模仿)
- CSS(四)
- 19.3.25 sql查询语句
- nodejs+express+socket.io
- MRO
- 【BZOJ3165】[HEOI2013]Segment(李超线段树)
- 查看mysql库中所有表的信息--INFORMATION_SCHEMA
热门文章
- shell编程报错 [: missing `]&#39;
- 微信开发学习日记(八):7步看懂weiphp插件机制,核心目标是响应微信请求
- HTML前端
- Redis和Memcache的区别分析
- 【Python】Django 聚合 Count与Sum用法,注意点
- TCP/IP详解学习笔记(5)-- ICMP:internet 控制报文协议
- 对于sharepoint 的解决方案的实际说明
- swift 中String,Int 等类型使用注意,整理中
- Java for LeetCode 141 Linked List Cycle
- [Android Pro] PackageManager#getPackageSizeInfo (hide)