第一届河北工业大学程序设计竞赛校赛

D-公园游玩
看了题目一看是要求遍历所有点的最短路径方法数,心想着去求最短路径,结果tmd根本不用求,只需要把输入时相邻的每两个点的方法数相乘就是结果了;

接下来说一下怎么求两点之间最短路径的方案数,从a(x1,y1),b(x2,y2),从a到b至少要走|x1-x2|+|y1-y2|步,其中要沿着x轴移动|x1-x2|步,沿着y轴移动|y1-y2|步,什么时候沿着x轴移动或沿着y轴移动无关紧要,关键是要在x轴或y轴移动这么多的步数,那就牵扯到组合问题了,就是在|x1-x2|+|y1-y2|中找出|x1-x2|个数的组合方法;

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const LL MOD=1e9+7;
const int N=2e5+10;

LL f[N];
LL n,m,k;
LL res=1;
LL qmi(LL a,LL b)//快速幂
{
    LL res=1;
    while(b)
    {
        if(b&1)res=res*a%MOD;
        b=b/2;
        a=a*a%MOD;
    }
    return res%MOD;
}
LL get(LL y,LL x)//求组合数
{
    return (f[y+x]%MOD)*qmi(f[x]*f[y]%MOD,MOD-2)%MOD;//万能费马小定理
}
int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);


    cin>>n>>m>>k;
    f[0]=1;
    for(int i=1; i<=n+m; i++)f[i]=f[i-1]*i%MOD;
    LL x,y;
    x=y=1;
    while(k--)
    {
        LL a,b;
        cin>>a>>b;
        res=res*get(abs(a-x),abs(b-y))%MOD;
        x=a;
        y=b;
    }
    res=res*get(abs(n-x),abs(m-y))%MOD;
    cout<<res<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值