hdu5106(组合数学)
来源:互联网 发布:网络位置是什么 编辑:程序博客网 时间:2024/04/29 12:49
题意:给一个二进制数R,长度不超过1000,问比R小并且1的个数为n的二进制数的和是多少。
解法:其实只需要枚举某个二进制数和R第一个1不同的位置就行了。因为如果R某个位置的1变成了0,那么以后01就随便取变成了组合数的问题。求和就预处理下1000内2的幂和前缀和了。我做时候复杂化,又求了小于等于R且1个数是n的二进制了。其实不用这一步了。
代码:
/******************************************************* @author:xiefubao*******************************************************/#pragma comment(linker, "/STACK:102400000,102400000")#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <queue>#include <vector>#include <algorithm>#include <cmath>#include <map>#include <set>#include <stack>#include <string.h>//freopen ("in.txt" , "r" , stdin);using namespace std;#define eps 1e-8#define zero(_) (abs(_)<=eps)const double pi=acos(-1.0);typedef long long LL;const int Max=1010;const LL INF=1000000007 ;LL C[Max][Max];LL po[Max];LL sum[Max];char s[Max];int n;void init(){ for(int i=0; i<Max; i++) for(int j=0; j<=i; j++) C[i][j]= j==0?1:(C[i-1][j-1]+C[i-1][j])%INF; po[0]=1; sum[0]=1; for(int i=1; i<Max; i++) { po[i]=po[i-1]*2%INF; sum[i]=(sum[i-1]+po[i])%INF; }}LL getans(bool f){ int have=0; LL ans=0; int len=strlen(s); LL be=0; for(int i=0; i<len; i++) { int sheng=len-1-i; int ge=n-have-1; if(s[i]=='1') { ans=(ans+(C[sheng-1][ge]*sum[sheng-1]%INF)%INF)%INF; //cout<<"be: "<<be<<" "<<C[sheng+1][ge+1]<<endl; //cout<<ans<<" "; ans=(ans+be*C[sheng][ge+1]%INF)%INF; //cout<<ans<<endl; if(f)ans=(ans+po[len-i-1])%INF; be=(be+po[len-i-1])%INF; //cout<<ans<<endl; have++; } } return ans%INF;}LL solve(){ int len=strlen(s); int m=0; for(int i=0; i<len; i++) if(s[i]=='1') m++; if(m<n) { int now=0; int need=n-m+1; int i; for(i=len-1; i>=0; i--) { if(s[i]=='0') now++; if(now==need) break; } for(; i>=0; i--) { if(s[i]=='1') { s[i]='0'; i++; for(; i<len; i++) { if(s[i]=='0') { need--; s[i]='1'; } if(need==0) break; } int j=i+1; i++; for(;i<len;i++) { if(s[i]=='1') { s[i]='0'; s[j++]='1'; } } break; } } } else if(n<m) { int need=m-n; for(int i=len-1; i; i--) { if(s[i]=='1') s[i]='0',need--; if(need==0) break; } } int sad=0; for(int i=0; i<len; i++)if(s[i]=='1')sad++; if(sad!=n) return 0; //puts(s); return getans(m!=n);}int main(){ init(); while(scanf("%d%s",&n,&s)==2) { if(n>strlen(s)||n==0) cout<<"0"<<endl; else cout<<solve()<<endl; } return 0;}
0 0
- hdu5106(组合数学)
- hdu5106 组合
- 组合数学
- 组合数学
- 组合数学
- 组合数学
- 组合数学
- 组合数学
- 组合数学
- 组合数学
- 组合数学
- 组合数学
- 组合数学
- 组合数学
- 组合数学
- 组合数学
- 组合数学
- 组合数学
- 【Allwinner ClassA20类库分析】8.GP类的使用
- (软工视频总结二)让我们将知识细化
- 第12周项目1 阅读程序(3递归函数)
- MVC 中 使用unobtrusive ajax 局部更新
- 亿级Web系统搭建——单机到分布式集群
- hdu5106(组合数学)
- FOJ有奖月赛-2014年11月 题解
- linux学习之二十二---命令行参数分析
- 折线分割平面 --- 递推求解
- Java——传值还是引用
- ZOJ 3806 Incircle and Circumcircle
- 成员模板(member template)
- 数据结构 线索二叉树 原理及实现
- win7 64位配置java运行环境