[数论] 洛谷 P1641 生成字符串

题目描述

lxhgww最近接到了一个生成字符串的任务,任务需要他把n个1和m个0组成字符串,但是任务还要求在组成的字符串中,在任意的前k个字符中,1的个数不能少于0的个数。现在lxhgww想要知道满足要求的字符串共有多少个,聪明的程序员们,你们能帮助他吗?

输入输出格式

输入格式:

输入数据是一行,包括2个数字n和m

输出格式:

输出数据是一行,包括1个数字,表示满足要求的字符串数目,这个数可能会很大,只需输出这个数除以20100403的余数

输入输出样例

输入样例#1:
2 2
输出样例#1:
2

说明

limitation

每点2秒

对于30%的数据,保证1<=m<=n<=1000

对于100%的数据,保证1<=m<=n<=1000000

题解

  • 对于这题,我们可以考虑将全部的方案-不合法的方案=合法的方案
  • 先来考虑一下全部的方案,字符串的长度为n+m,在里面放n个1,方案数就是C(n+m,n)
  • 那么怎么求出不合法的情况的方案呢
  • 我们把放0、1当做是在平面直角坐标系上,放1就当做是(+1,+1),放0就当做是(+1,-1)那么当直线到达(x,-1)时,就是不合法的
  • 然后我们把y=-1当做是对称轴,将我们形成的直线对称下来,然后我们可以发现其实就是从(0,-2)开始到达(n+m,n-m)的方案数就是不合法滴
  • 最后的话,答案就是C(n+m,n)-C(n+m,m-1)

代码

 1 #include <iostream>
 2 #include <cstdio>
 3 #define ll long long
 4 using namespace std;
 5 const ll mo=20100403;
 6 ll n,m,p[2000050],q[2000050];
 7 ll C(ll x,ll y) { return q[x]*p[y]%mo*p[x-y]%mo; }
 8 int main()
 9 {
10     scanf("%lld%lld",&n,&m),p[0]=p[1]=q[0]=q[1]=1;;
11     for (ll i=2;i<=n+m;i++) p[i]=(mo-mo/i)*p[mo%i]%mo,q[i]=q[i-1]*i%mo;
12     for (ll i=2;i<=n+m;i++) p[i]=p[i-1]*p[i]%mo;
13     printf("%lld",((C(n+m,m)-C(n+m,m-1))%mo+mo)%mo);
14     return 0;
15 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/10324738.html