HDU3398—String-(组合数)
Problem Description
Recently, lxhgww received a task : to generate strings contain '0's and '1's only, in which '0' appears exactly m times, '1' appears exactly n times. Also, any prefix string of it must satisfy the situation that the number of 1's can not be smaller than the number of 0's . But he can't calculate the number of satisfied strings. Can you help him?
Input
T(T<=100) in the first line is the case number.
Each case contains two numbers n and m( 1 <= m <= n <= 1000000 ).
Output
Output the number of satisfied strings % 20100501.
Sample Input
1
2 2
Sample Output
2
Author
lxhgww
Source
HDOJ Monthly Contest – 2010.05.01
Recommend
lcy
题意为一个字符串只由0,1组成,且0有m个,1有n个,要求该字符串中任意的前缀中1的个数不能小于0的个数,问这样的字符串一共有多少个。结果对20100501取模。
将构造字符串的过程转化到二维坐标上去,1用y表示,0用x表示,从坐标(0,0)出发,0代表向右走(x增加),1代表向上走(y增加),因为0有m个,1有n个,所以最后到达的坐标为
(m,n) ,单纯考虑从0,0走到m,n一共有C(n+m,m)种方法,又因为任意前缀中1的个数不能小于0,所以y>=x,也就是合法走的路线经过的坐标要么在y=x上,要么在其上边,那么
不合法的路线经过的坐标则满足y<x,也就是路线不能与y=x-1相交,因为只要一相交,就不满足1的个数不能小于0的个数。
所以不合法的路径一定与y=x-1相交,找到(0,0)关于y=x-1的对称点(1,-1),从(1,-1)走到(m,n)一定与直线y=x-1相交,因为m,n在该直线的上边,1,-1在该直线的下
边。在这里设交点为P,那么路线就以P为分割点可以分为两部分,上面一部分取个名字叫不合法路线,下面一部分取个名字叫合法路线。那么从1,-1走到m,n有多少种方法也就
是从0,0走到m,n的不合法的方法数。仔细想一想为什么呢?为什么要找对称点,在对称直线一侧走的路线总可以在另一侧找到路线与之对称,刚才我们从1,-1走到m,n的那一段
合法路线沿着y=x-1再对称过去,不合法路线就不用对称了,因为不合法路线已经与y=x-1相交了(其实那一段合法路线的最后一个点也与y=x-1相交),这样就有了从0,0到m,n
的一种方案,总的来说就是对于从1,-1到m,n的每一条路线,都有从0,0到m,n关于y=x-1对称的一条路线与之对应。从1,-1走到m,n方法数为C (m+n,m-1)。
所以本题的答案就是C(n+m,m) - C (m+n,m-1)。
那么接下来的问题就是求上面的式子了。
上面式子最终可以化为 (n+1-m)*(n+m)! / (m! *(n+1)!)
直接求肯定不行,因为涉及到了除法的取模运算。
考虑整数唯一分解定理:
任意正整数都有且只有一种方式写出其素因子的乘积表达式。
A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn) 其中pi均为素数
那么可以把每个数都化成这样的形式,然后上下对于相同的素因子进行约分,也就是指数相减,对于一个素数pi,我们只要知道最终pi的指数是多少就可以了(上下都约分后的指数)
还有把阶层看作一个数,比m! 怎样求m!里面素数2的指数呢?
cnt=0; while(m) { m/=2; cnt+=m; } 就可以了,为什么呢?考虑m=4,则m!= 4*3*2*1, 第一次m/=2,是计算m!里面有多少个数能整除2的(有4,2),所以cnt+=2,有两个数贡献了两个素数2,接下来第二次m/=2,是计算m!里面有多少个数能整除4的,有1个数又贡献了一个素数2.
代码:
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=1000000;
const int mod=20100501;
bool isprime[maxn*2+10];
int prime[maxn*2+10];
int len=0;//素数的个数
int n,m;
int t; void sieve(int n)//筛n以内的素数
{
for(int i=0;i<=n;i++)
isprime[i]=1;
isprime[0]=isprime[1]=0;
for(int i=2;i<=n;i++)
if(isprime[i])
{
prime[len++]=i;
for(int j=2*i;j<=n;j+=i)
isprime[j]=0;
}
} int cal(int p,int n)//计算n!里面有多少个p相乘
{
int ans=0;
while(n)
{
n/=p;
ans+=n;
}
return ans;
} int main()
{
sieve(maxn*2);
cin>>t;
while(t--)
{
long long ans=1;//记得要用long long
cin>>n>>m;
int nm=n+1-m;
for(int i=0;i<len&&prime[i]<=(n+m);i++)//prime[i]<=(n+m)是因为拆成素数幂相乘的形式该素数不会大于n+m,最大(n+m)! (n+m)*(n+m-1)*(n+m-2).....
{
int cnt=0;//分解为素数prime[i]的指数是多少
while(nm%prime[i]==0)//nm中有多少个prime[i],也就是把nm分解后prime[i]的指数
{
nm/=prime[i];
cnt++;
}
cnt=cnt+cal(prime[i],n+m)-cal(prime[i],m)-cal(prime[i],n+1);//加上分子的指数再减去分母的指数
for(int j=1;j<=cnt;j++)
{
ans=ans*prime[i];
if(ans>=mod)
ans%=mod;
}
}
cout<<ans<<endl;
}
return 0;
}
HDU3398—String-(组合数)的更多相关文章
- LCM性质 + 组合数 - HDU 5407 CRB and Candies
		CRB and Candies Problem's Link Mean: 给定一个数n,求LCM(C(n,0),C(n,1),C(n,2)...C(n,n))的值,(n<=1e6). analy ... 
- 计算一维组合数的java实现
		背景很简单,就是从给定的m个不同的元素中选出n个,输出所有的组合情况! 例如:从1到m的自然数中,选择n(n<=m)个数,有多少种选择的组合,将其输出! 本方案的代码实现逻辑是比较成熟的方案: ... 
- C++单元测试 之 gtest -- 组合数计算.
		本文将介绍如何使用gtest进行单元测试. gtest是google单元测试框架.使用非常方便. 首先,下载gtest (有些google项目包含gtest,如 protobuf),复制目录即可使用. ... 
- UOJ263 【NOIP2016】组合数问题
		本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ... 
- 2014多校第六场 1007 || HDU 4927 Series 1(杨辉三角组合数)
		题目链接 题意 : n个数,每操作一次就变成n-1个数,最后变成一个数,输出这个数,操作是指后一个数减前一个数得到的数写下来. 思路 : 找出几个数,算得时候先不要算出来,用式子代替,例如: 1 2 ... 
- codeforces 630F Selection of Personnel(组合数)
		F. Selection of Personnel time limit per test 0.5 seconds memory limit per test 64 megabytes input s ... 
- hdu 3944 DP? 组合数取模(Lucas定理+预处理+帕斯卡公式优化)
		DP? Problem Description Figure 1 shows the Yang Hui Triangle. We number the row from top to bottom 0 ... 
- nyoj 32 组合数【简单dfs】
		组合数 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 找出从自然数1.2.... .n(0<n<10)中任取r(0<r<=n)个数的所有组合 ... 
- HDU 5396 Expression(DP+组合数)(详解)
		题目大意: 给你一个n然后是n个数. 然后是n-1个操作符,操作符是插入在两个数字之间的. 由于你不同的运算顺序,会产生不同的结果. 比如: 1 + 1 * 2 有两种 (1+1)*2 或者 ... 
- 深搜最基础题---全排列And组合数
		这个是理解标记和取消标记,用一个vis数组来标记 全排列代码: #include <stdio.h> ]; ]; int n; void dfs(int step)//step是当前已经进 ... 
随机推荐
- HDU 6175 算术
			题目大意 求 $\sum_{i = 1}^{n} \sum_{j = 1}^{m} \mu(\lcm(i, j))$ . $ 1 \le n, m \le 10^6 $ . 分析 不妨设 $ n \l ... 
- Servlet概念及与Jsp的区别
			一.Servlet概念 Servlet是在服务器上运行的小程序.一个Servlet就是一个Java类,并且可以通过”请求-响应”编程模型来访问这个驻留在服务器内存里的Servlet程序 二.Servl ... 
- 从window 的cmd窗口中下载linux 服务器上文件
			下载linux 服务器上的文件 down.php 格式为 pscp linux服务器上用户名@linux 服务器ip 文件在windows系统上的绝对路径 如果是下载服务器上的某个目录,只要在ps ... 
- 使用elasticsearch7.3版本在一台主机上部署多个实例组建集群
			系统:centos 7.4 x64 主机ip:192.168.0.160 软件包:elasticsearch-7.3.0-linux-x86_64.tar.gz 配置步骤 vim /etc/secur ... 
- 实现 RSA 算法之基础公式证明(第一章)(老物)
			写这篇日志是拖了很久的事情,以前说要写些算法相关的文章给想学信息安全学(简称信安),密码学的同学提供些入门资料,毕竟这种知识教师上课也不会细讲太多(纯理论偏重),更不用说理解和应用了,说到RSA公钥( ... 
- npm 命令行基本操作
			npm命令选项选项 说明search 在存储库中查找模块包 npm search expressinstall 使用在存储库或本地位置上的一个package.json文件来安装 ... 
- 通过SEO可以做什么?
			1.做关键词排名,从而带来大量的客户卖产品和服务.很多大型机械厂家就是这么做的,显然SEO赚取了不少利润. 2.通过SEO带来大量流量,从而投放广告或者跟厂家合作买产品,比如流量站之类. ... 
- pycharm解释器链接如何pymongo
			1.pymongo 链接数据库 # pycharm 链接我们的mogodb # 下载pymongo from pymongo import MongoClient # 客户端请求 服务端 # 链接 c ... 
- kali 下安装 vmtools
			网上的教程都是默认路径下的,kali是定制版本的,路径不同,所以首先要找到media下安装包的路径,然后进入该路下,将安装包复制到想要的路径下,并解压缩到想要的路径下,剩下的就跟网上的差不多了,即找到 ... 
- SOA架构简介
			一. 什么是SOA 架构 SOA是一种架构模型,它可以根据需求通过网络对松散耦合的粗粒度应用组件进行分布式部署.组合和使用.服务层是SOA的基础,可以直接被应用调用,从而有效控制系统中与软件代理交互的 ... 
