• 51nod 1118 机器人走方格


    M * N的方格,一个机器人从左上走到右下,只能向右或向下走。有多少种不同的走法?由于方法数量可能很大,只需要输出Mod 10^9 + 7的结果。
     

    输入

    第1行,2个数M,N,中间用空格隔开。(2 <= m,n <= 1000)

    输出

    输出走法的数量。

    输入样例

    2 3

    输出样例

    3
    动态规划代码:
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define MAX 1000
    #define DMAX 10000
    #define MOD 1000000007
    using namespace std;
    typedef long long ll;
    int m,n;
    ll dp[MAX + 1][MAX + 1];
    
    int main() {
        scanf("%d%d",&m,&n);
        dp[1][1] = 1;
        for(int i = 1;i <= m;i ++) {
            for(int j = 1;j <= n;j ++) {
                dp[i][j] += dp[i][j - 1] + dp[i - 1][j];
                dp[i][j] %= MOD;
            }
        }
        printf("%lld",dp[m][n]);
    }

    可以用组合数,因为在每个位置要么选择横着走,要么选择竖着走,我们发现横着跨越的边或者竖着跨越的边的数量是一定的,分别是n - 1和m - 1,所以我们只需要把横着跨越的位置选好,或者把竖着的选好,剩下的就是横着走的了。

    1,1  1,2  1,3  1,4

    2,1  2,2  2,3  2,4

    3,1  3,2  3,3  3,4

    如上,我们先把竖着跨越的选好,显然选m-1=2个,第一个选1,2->2,2吧,第二选2,4->3,4这样我们需要连接n-1=3条边,1,1->1,2,2->2,3,2,3->2,4,横的竖的只要有一个选好了,另一个就定下了,所以只需要计算其中一个选择有几种情况即可。总的需要走n+m-2步,即需要跨越这么多个格子的边界,具体把哪几步分配给横着(竖着)走,可以用组合数来完成,而这里数据大需要取模,组合数有分子分母,取模要用到逆元。

    组合代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define MAX 1000
    #define DMAX 10000
    #define MOD 1000000007
    using namespace std;
    typedef long long ll;
    int m,n;
    int exgcd(int a,int b,int &x,int &y) {
        if(b == 0) {
            x = 1,y = 0;
            return a;
        }
        int g = exgcd(b,a % b,y,x);
        y -= a / b * x;
        return g;
    }
    int c(int x,int y) {
        ll ans = 1;
        int a,b;
        for(int i = y;i > y - x;i --) {
            ans = (ans * i) % MOD;
        }
        for(int i = 2;i <= x;i ++) {
            exgcd(i,MOD,a,b);
            a = (a + MOD) % MOD;
            ans = (ans * a) % MOD;
        }
        return ans;
    }
    int main() {
        scanf("%d%d",&m,&n);
        printf("%d",c(min(m - 1,n - 1),n + m - 2));
    }

     可以用卢卡斯定理专门求组合数。

    lucas代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define MAX 1000000
    #define DMAX 1000000
    #define MOD 1000000007
    using namespace std;
    typedef long long ll;
    int m,n;
    ll pow_mod(ll a,ll b,ll p) {///quick_pow
        ll ans = 1;
        while(b) {
            if(b % 2) ans = (ans * a) % p;
            a = (a * a) % p;
            b >>= 1;
        }
        return ans;
    }
    ll c(ll a,ll b,ll p) {///c(b,a)
        ll ans = 1,temp = 1;
        for(int i = 0;i < b;i ++) {
            ans = (ans * (a - i)) % p;
            temp = (temp * (b - i)) % p;
        }
        temp = pow_mod(temp,p - 2,p);///变成逆元 费马定理
        ans = (ans * temp) % p;
        return ans;
    }
    ll lucas(ll a,ll b,ll p) {//main
        ll ans = 1;
        while(a && b) {
            ans = (ans * c(a % p,b % p,p)) % p;
            a /= p;
            b /= p;
        }
        return ans;
    }
    int main() {
        scanf("%d%d",&m,&n);
        printf("%d",lucas(n + m - 2,n - 1,MOD));
    }
  • 相关阅读:
    [CF340D]Bubble Sort Graph/[JZOJ3485]独立集
    [JZOJ3484]密码
    [HDU1756]Cupid's Arrow
    Luogu P4006 小 Y 和二叉树
    Luogu P4040 [AHOI2014/JSOI2014]宅男计划
    Luogu P3243 [HNOI2015]菜肴制作
    Luogu P3942 将军令
    Luogu P4823 [TJOI2013]拯救小矮人
    Luogu P3620 [APIO/CTSC 2007]数据备份
    BZOJ3709 [PA2014]Bohater
  • 原文地址:https://www.cnblogs.com/8023spz/p/10028807.html
Copyright © 2020-2023  润新知