zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    Android 按键消息处理Android 按键消息处理
    objcopy
    SQLite多线程读写实践及常见问题总结
    android动画坐标定义
    Android动画效果translate、scale、alpha、rotate
    Android公共库(缓存 下拉ListView 下载管理Pro 静默安装 root运行 Java公共类)
    Flatten Binary Tree to Linked List
    Distinct Subsequences
    Populating Next Right Pointers in Each Node II
    Populating Next Right Pointers in Each Node
  • 原文地址:https://www.cnblogs.com/Lyush/p/2594889.html
Copyright © 2011-2022 走看看