hdu 5698瞬间移动(组合数取模、卢卡斯定理)

瞬间移动

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1927    Accepted Submission(s): 872

 

Problem Description

有一个无限大的矩形,初始时你在左上角(即第一行第一列),每次你都可以选择一个右下方格子,并瞬移过去(如从下图中的红色格子能直接瞬移到蓝色格子),求到第n  行第m  列的格子有几种方案,答案对1000000007  取模。

http://acm.hdu.edu.cn/../../data/images/C702-1003-1.jpg

 

 

Input

多组测试数据。

两个整数n,m(2≤n,m≤100000)  

 

 

Output

一个整数表示答案

 

 

Sample Input

4 5

 

 

Sample Output

10

 

 

Source

2016"百度之星" - 初赛(Astar Round2B)

 

 

Recommend

wange2014

 
算法分析:

确实这个规律,想不到啊

杨辉三角打表 

1 1 
1 2 1 

1 3 3 1 
4 6 4 1 
1 5 
10 10 5 1 
1 6 15 
20 15 6 1

我们发现规律就是求组合数C(n+m-4,m-2)

代码实现:

#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
typedef long long LL;
const LL p=1e9+7; 
//适用于p很大 
LL quick_mod(LL a, LL b)     //快速幂
{
    LL ans = 1;
    a %= p;
    while(b)
    {
        if(b & 1)
        {
            ans = ans * a % p;
            b--;
        }
        b >>= 1;
        a = a * a % p;
    }
    return ans;
}
 
LL C(LL n, LL m)      //求组合C(n,m)
{
    if(m > n) return 0;    //n<m, c(n,m)=0
    LL ans = 1;
    for(int i=1; i<=m; i++)
    {
        LL a = (n + i - m) % p;
        LL b = i % p;
        ans = ans * (a * quick_mod(b, p-2) % p) % p;
    }
    return ans;
}
 
LL Lucas(LL n, LL m)     //lucass定理
{
    if(m == 0) return 1;
    return C(n % p, m % p) * Lucas(n / p, m / p) % p;
}
 
int main()
{
	LL n,m;
    while(scanf("%I64d%I64d", &n, &m)!=EOF)
    {
         
        printf("%I64d\n", Lucas(m+n-4,m-2));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sdz20172133/article/details/81672924
今日推荐