【GDOI2014模拟】网格

本文介绍了一种计算从网格左下角到右上角特定点的合法路径数量的方法。通过利用组合数学原理,避免经过特定区域,实现了路径计数。文章提供了一段C++代码实现,用于高效计算合法路径的数量。

Description

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

分析

首先,我们知道:如果现在从(0, 0)点出发,只能沿着街道向正右方或者正上方行走时,到(n,m)点(n>=m)的方案数是Cmn+m。
发现,任何途径的点(x, y)都要满足x>=y就是不经过粉色线x=y+1
这里写图片描述
有一条违法的路径:
这里写图片描述
我们把路径按照粉色线做个对称,
这里写图片描述
我们发现,到橙色点的路径都一一对应每一条违法路径,也就是说,违法路径的方案数就是到橙色点的方案数。
所以,合法方案数=随便走的方案数-违法方案数= Cmn+m - Cm1n+m
注意:如果直接算可能会超时,要把式子简化,而且高精度要压位。
(转自http://blog.youkuaiyun.com/chen1352/article/details/51648846)

#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
using namespace std;
const int mo=10000;
int n,m,t,f[10000]; 
void cheng(int x)
{
    int t=0;
    for (int i=1;i<=f[0];i++)
    {
        f[i]=f[i]*x+t;
        t=f[i]/mo;
        f[i]=f[i]%mo;
    }
    if (t>0) f[++f[0]]=t;
}
void chu(int x)
{
    int t=0;
    for (int i=f[0];i>=1;i--)
    {
        int p=f[i]+t;
        f[i]=p/x;
        t=p%x*mo;
    }
    while (f[f[0]]==0 && f[0]>0) f[0]--;
}
void write()
{
    printf("%d",f[f[0]]);
    for (int i=f[0]-1;i>=1;i--)
    {
        int t=mo/10;
        while (f[i]<t && t!=0)
        {
            printf("%d",0);
            t/=10;
        }
        printf("%d",f[i]);
    }
}
int main()
{
    scanf("%d%d\n",&n,&m);
    f[0]=1;
    f[1]=n+1-m;
    for (int i=n+2;i<=n+m;i++) cheng(i);
    for (int i=2;i<=m;i++) chu(i);
    write();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值