HUT-1943 黑箱

直接用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;
}
posted @ 2012-07-17 11:05  沐阳  阅读(230)  评论(0编辑  收藏  举报