BZOJ 3907
Description
某城市的街道呈网格状,左下角坐标为A(0, 0),右上角坐标为B(n, m),其中n >= m。现在从A(0, 0)点出发,只能沿着街道向正右方或者正上方行走,且不能经过图示中直线左上方的点,即任何途径的点(x, y)都要满足x >= y,请问在这些前提下,到达B(n, m)有多少种走法。

Input
输入文件中仅有一行,包含两个整数n和m,表示城市街区的规模。
Output
输出文件中仅有一个整数和一个换行/回车符,表示不同的方案总数。
Sample Input
6 6
Sample Output
132
分析:
n= m时,退化为《组合数学》例题,向上为-1,向左为1,如果过线,则存在\(k\) 使得\(\sum_{j= 1}^{j <= k} < 0\) 然后,满足卡特兰递推关系。。。
n != m
证明思想类似那个那个例题思想。就是翻转-1,和1串,发现每个不合法串对应一个翻转后的串
我们假设1表示向右走,-1表示向上走,那么很显然问题可以转化为:给你n个1和m个-1,求出满足某个条件的数列的个数,这个条件是——对于任意一个数列s[1…i],和大于等于0。我们可以用补集转化的方法,所有的个数为\((_{n+m}^{m})\),然后我们再考虑不合法的个数。我们假定现在有一个数列,它的1和-1的个数分别是n和m,第一次出现不满足条件的位置是i。即s[1…i]当中,-1的个数=1的个数+1,并且s[i]=-1。我们把s[1…i]的所有-1变成1,1变成-1,这样,我们得到的新的数列,这个数列当中,1和-1的个数分别为n+1,m-1。我们发现,这个转化是一一对应的,也就是说,每一个不合法的数列,都对应了一个唯一的一个n+1,m-1的数列;而这个n+1,m-1的数列也正好和唯一的这个不合法串对应,满足充要性。于是我们得到了不合法的01串的个数就是\((_{n+m}^{m−1})\)。
然后拿全集-补集。得到答案
代码,很久没搞python,基本忘光了。
蒯了一份。
不过也就那几样。很容易想起来的。
python 代码。
fac={};
def C(n,m):
return fac[n]/fac[m]/fac[n-m];
fac[0]=1;
for i in range(1,10000):
fac[i]=fac[i-1]*i;
f=raw_input().split(" ");
n=int(f[0]);m=int(f[1]);
print(C(n+m,n)-C(n+m,n+1));
算好阶乘,直接算。自带高精度就是任性

浙公网安备 33010602011771号