【BZOJ3907】网格 组合数,补集转换

该博客详细解析了BZOJ3907题目,涉及从(0,0)到(n,m)的路径计数问题,通过组合数Cmn+m表示所有路径,并讨论了如何排除穿过y=x线的路径。博客提出了一个特殊的技巧,将不穿过y=x线的路径转化为不经过该线的问题,通过计算全集和补集的差值得到答案。当n=m时,答案与卡特兰数有关。" 120120330,11364812,Java并发编程:ThreadPoolExecutor详解,"['Java', '并发编程', '线程池']

链接:

#include <stdio.h>
int main()
{
    puts("转载请注明出处[vmurder]谢谢");
    puts("网址:blog.csdn.net/vmurder/article/details/44944381");
}

题解:

      首先从 (0,0)(n,m) 是右走 n 步, 上走 m 步。方案数是在 n 个数中 n+1 个空中插 m 个数,组合数是Cmn+m
      然后从中减去穿过 y=x 这条线的那些方案数就好了。

      但是这个很难求,而若要求 [ 不经过 ] 则就可以有特别的技巧了。
      假设第一步向上,那么最终无论如何都要经过这条线,因为向上已经走一步,所以需要去掉的方案数则为 Cm1n+m1
      然后如果第一步向右,则若一个方案从起点到最后一次经过 y=x 这条线的那个点的整个路径都沿 y=x 这条直线翻转,剩余到终点 (n,m) 的路径不进行变动,则正好对应唯一一种第一步向上走的方案。而这种情况的方案数则为 Cn1n+m1
      所以求不经过,答案则是 Cmn+m2Cm1n+m1

      那么我们怎么转化成不穿过呢?
      观察发现第一步向上,则定然不符合要求需要被删掉;而第一步向右,满足要求的所有方案,因为无法经过 y=x 这条直线,所以它们被一条无形的线 y=x1 禁锢着,只要越过这条线就会碰触到 y=x 。所以 [ 不经过 ] 情况下的询问 (n,m) 正好对应着 [ 不穿过 ] 情况下的询问 (n1,m)

所以最终答案是 Cmn+m+12Cm1n+m

特殊的骗分技巧:

n==m时答案是卡特兰数哦骚年~
这个可以打表发现!

代码:

def Fac(n):
    ans=1
    for i in range(2,n+1):
        ans=ans*i
    return ans
def C(n,m):
    if (n<m):
        return 0
    return (Fac(n)/Fac(m)/Fac(n-m))
n,m=raw_input().split()
n=int(n)
m=int(m)
print C(n+m+1,m)-2*C(n+m,m-1)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值