HDU 5698 瞬间移动 (2016"百度之星" - 初赛(Astar Round2B) 1003)
Posted ITAK
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5698 瞬间移动 (2016"百度之星" - 初赛(Astar Round2B) 1003)相关的知识,希望对你有一定的参考价值。
传送门
瞬间移动
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 140 Accepted Submission(s): 66
Problem Description
有一个无限大的矩形,初始时你在左上角(即第一行第一列),每次你都可以选择一个右下方格子,并瞬移过去(如从下图中的红色格子能直接瞬移到蓝色格子),求到第n行第m列的格子有几种方案,答案对1000000007取模。
Input
多组测试数据。
两个整数n,m(2≤n,m≤100000)
Output
一个整数表示答案
Sample Input
4 5
Sample Output
10
Source
2016”百度之星” - 初赛(Astar Round2B)
解题思路:
首先我们分析一下这个题其实就是我们要从(1, 1)点走到(n, m)点,而且只能走右下方,那么我们就相当于从(n+m-4)个格子里选n-2(或者是m-2)个格子,因为我们得去掉n-1行和m-1列(这个不能选),然后再去掉第一行和第一列,所以就是
因为这个数要对MOD取余,那么我们需要求一下(n-2)!*(m-2)!关于MOD的逆元,这个其实一个循环就行,每次扩展欧几里得一下,就OK了,最后就是编码了,
第一步:写一个扩展欧几里得算法,求a关于b的逆元;
第二步:根据公式,一步步的求,先求(n+m-4)!模上MOD,然后再for循环求两个阶乘的逆元
第三步:输出结果。
上代码:
#include <iostream>
using namespace std;
typedef long long LL;
const LL MOD = 1000000007;
void exgcd(LL a, LL b, LL &x, LL &y)
{
if(b == 0)
{
x = 1;
y = 0;
return;
}
LL x1, y1;
exgcd(b, a%b, x1, y1);
x = y1;
y = x1-(a/b)*y1;
}
int main()
{
LL n, m;
while(cin>>n>>m)
{
LL ans = 1;
for(LL i=1; i<=n+m-4; i++)
ans = (ans*i)%MOD;
for(LL i=1; i<=n-2; i++)
{
LL x, y;
exgcd(i, MOD, x, y);
x = (x%MOD+MOD)%MOD;
ans = (ans*x)%MOD;
}
for(LL i=1; i<=m-2; i++)
{
LL x, y;
exgcd(i, MOD, x, y);
x = (x%MOD+MOD)%MOD;
ans = (ans*x)%MOD;
}
ans = (ans%MOD+MOD)%MOD;
cout<<ans<<endl;
}
return 0;
}
以上是关于HDU 5698 瞬间移动 (2016"百度之星" - 初赛(Astar Round2B) 1003)的主要内容,如果未能解决你的问题,请参考以下文章