HDU 5698 瞬间移动(百度之星2016)

2016暑期集训2-J

HDU 5698 瞬间移动(百度之星2016)

想法+组合取模

传送门:HustOJ
传送门:HDU


题意

中文的,有图,开源网页吧。


思路

m行n列,每次至少往右走一步、往下走一步,所以一共往右走n-1格,往下走m-1格。所以最多走min(m-1,n-1)次。往右走往下走的次数相等,所以把m-1和n-1分别拆成k个数的和。k从1取到min(m-1,n-1)。拆数用隔板法组合。求出走k次的方法数,然后加起来就可以了。


代码

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<iomanip>

using namespace std;
const int MAXN = 100007;
const int oo = 2000000007;
const long long int loo = 1000000000000000007ll;
const int MOD = 1000000007;
typedef long double ld;
typedef long long ll;
ll fact [ MAXN ];
ll f [ MAXN ];
ll inv [ MAXN ];
ll CMOD ( ll a , ll b )
{
    b = min ( b , a - b );
    ll res = 1;
    res = res*fact [ a ];
    res %= MOD;
    res = res*inv [ a - b ];
    res %= MOD;
    res = res*inv [ b ];
    res %= MOD;
    return res;
}
int main ( )
{
    int m , n;
    memset ( fact , 0 , sizeof ( fact ) );
    memset ( f , 0 , sizeof ( f ) );
    memset ( inv , 0 , sizeof ( inv ) );
    fact [ 0 ] = 1;
    f [ 0 ] = 1;
    inv [ 0 ] = 1;
    fact [ 1 ] = 1;
    f [ 1 ] = 1;
    inv [ 1 ] = 1;
    for ( int i = 2; i < MAXN; i++ )
    {
        fact [ i ] = ( fact [ i - 1 ] * i ) % MOD;
        f [ i ] = ( MOD - MOD / i )*f [ MOD%i ] % MOD;
        inv [ i ] = inv [ i - 1 ] * f [ i ] % MOD;
    }

    while ( scanf ( "%d%d" , &n , &m ) == 2 )
    {
        n--;
        m--;
        ll res = 0;
        for ( int i = 1; i <= min ( m , n ); i++ )
        {
            res += ( CMOD ( m - 1 , i - 1 ) * CMOD ( n - 1 , i - 1 ) );
            res %= MOD;
        }
        printf ( "%I64d\n" , res );
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值