• HUT1943 黑箱


    直接用DP方程直接TLE了,因为数据范围达到了10^9......

    这题的正解是先用DP方程分别求出在t步走到每一行(列)的可能,再将其相加到一个步数为t的数组中,表示到第t步时,所有行(列)的种数,最后再用一个组合公式,将规定的K步进行分解来求得最后的答案。这题要特别要注意边界条件,还有就是防止溢出。这里用到了一个公式来求组合数 C[i, j] = C[i-1, j] + C[i-1, j-1]。

    代码如下:

    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #define MOD 1000000007
    using namespace std;
    
    int N, M, K, x, y;
    
    int C[1005][1005], _r[1005][1005], _c[1005][1005];
    
    int kr[1005], kc[1005];
    
    void pre()
    {
        for (int i = 0; i <= 1000; ++i) {
            C[i][0] = 1;
            for (int j = 1; j <= i; ++j) {
                C[i][j] = (C[i-1][j] + C[i-1][j-1]) % MOD;
            /*    printf("%d %d %d\n", i, j, C[i][j]);
                getchar(); */
            }
        }
    }
    
    void add()
    {
    
    }
    
    void go()
    {
        memset(_r, 0, sizeof (_r));
        memset(_c, 0, sizeof (_c));
        memset(kr, 0, sizeof (kr));
        memset(kc, 0, sizeof (kc));
        _r[0][x] = 1, _c[0][y] = 1;
        for (int t = 1; t <= K; ++t) {
        //    printf("t = %d, N = %d\n", t, N);
            for (int i = 1; i <= N; ++i) {
                if (i - 1 >= 1) {
                    _r[t][i-1] += _r[t-1][i];
              //      printf("%d %d %d\n", t, i-1, _r[t][i-1]);
                    _r[t][i-1] %= MOD;
                }
                if (i + 1 <= N) {
                    _r[t][i+1] += _r[t-1][i];
               //     printf("%d %d %d\n", t, i+1, _c[t][i+1]);
                    _r[t][i+1] %= MOD;
                }
            }
            for (int j = 1; j <= M; ++j) {
                if (j - 1 >= 1) {
                    _c[t][j-1] += _c[t-1][j];
                    _c[t][j-1] %= MOD;
                }
                if (j + 1 <= M) {
                    _c[t][j+1] += _c[t-1][j];
                    _c[t][j+1] %= MOD;
                }
            }
        }
        
        for (int t = 0; t <= K; ++t) {
            for (int i = 1; i <= N; ++i) {
                kr[t] += _r[t][i]; // 把每个步数下走到所有可能相加
                kr[t] %= MOD;
            }
            for (int j = 1; j <= M; ++j) {
                kc[t] += _c[t][j];
                kc[t] %= MOD;
            }
        }
        
    }
    
    int deal()
    {
        int ans = 0;
        for (int i = 0; i <= K; ++i) {
            ans += (long long)C[K][i] * kr[i] % MOD * kc[K-i] % MOD;
            ans %= MOD;
        }
        return ans % MOD;
    }
    
    int main()
    {
        pre();
        int T;
        scanf("%d", &T);
        while (T--) {
            scanf("%d %d %d %d %d", &N, &M, &K, &x, &y);
            go();
            printf("%d\n", deal());
        }
        return 0;
    }
  • 相关阅读:
    php 下载文件
    thinkphp3.1 发送email
    微擎 plugin 时间插件 图片上传插件不显示 报错 影响下面执行
    Java中基本数据类型的对比记忆
    堆内存设置以及垃圾回收方式
    try--catch--finally中return返回值执行的顺序(区别)
    Java中的值传递和引用传递
    全面总结sizeof的用法(定义、语法、指针变量、数组、结构体、类、联合体、位域位段)
    10进制转换成16进制最简单的方法
    quartz 框架定时任务,使用spring @Scheduled注解执行定时任务
  • 原文地址:https://www.cnblogs.com/Lyush/p/2594889.html
Copyright © 2020-2023  润新知