SP19149 INS14H

可以发现,如果一个整体一起考虑是不能找到一个合适的状态来描述这个情形的。

因此可以考虑寻找整体的反面,也就是将每个维度分开考虑。

不难发现每个维度本质上是一样的,因此不需要考虑不同维度之间的区别。

那么对于每个维度而言,它必须从 (0) 出发再回到 (0),那么假设它往外走了 (k) 步,那么往内也必然走了 (k) 步。

不难发现每个维度本质上是在总共的 (T) 步中选择了 (k) 个位置在这个维度上往外走,再选择 (k) 个位置往内走,于是就可以直接考虑 (dp) 了。

(dp_{i, j}) 表示前 (i) 个维度一共走了 (j) 步的方案,假设最终一共走的步数为 (T),那么有转移:

[dp_{i, j} = sumlimits_{k = 0} ^ {lfloor frac{j}{2} floor} dp_{i - 1, j - 2 imes k} imes dbinom{T - j + 2 imes k}{k} imes dbinom{T - j + k}{k} ]

这样就可以 (O(n ^ 3)) 地算了,但每次查询 (T) 都会改变,怎么办呢?

回到 (dp) 转移之前的这个流程,不难发现实质上本质上是 (2n) 个多重集合排列的问题。

回忆一下这个问题:(m) 个集合第 (i) 个集合内有 (a_i) 个元素不标号,满足 (sum a_i = n),问排列的方案数,不难发现即为:

[frac{n!}{a_1!a_2! cdots a_m!} ]

可以发现分母是与 (n) 无关的,而分子又是与每个 (a_i) 无关的。

因此我们在 (dp) 的过程中先不计算分子对答案的贡献,只计算分母对答案的贡献,最后查询直接乘 (T!) 即可。

实际上也可以考虑转移的时候以插入的形式转移,本质上是一致的,在此不再赘述。

#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = l; i <= r; ++i)
const int N = 200 + 5;
const int L = 200;
const int Mod = 1e9 + 7;
int n, T, Q, fac[N], inv[N], dp[N][N];
int read() {
    char c; int x = 0, f = 1;
    c = getchar();
    while (c > '9' || c < '0') { if(c == '-') f = -1; c = getchar();}
    while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int Inc(int a, int b) { return (a += b) >= Mod ? a - Mod : a;}
int Dec(int a, int b) { return (a -= b) < 0 ? a + Mod : a;}
int Mul(int a, int b) { return 1ll * a * b % Mod;}
int fpow(int a, int b) { int ans = 1; for (; b; a = Mul(a, a), b >>= 1) if(b & 1) ans = Mul(ans, a); return ans;}
int C(int n, int m) { return n < m ? 0 : Mul(fac[n], Mul(inv[m], inv[n - m]));}
int main() {
    fac[0] = inv[0] = dp[0][0] = 1;
    rep(i, 1, L) fac[i] = Mul(fac[i - 1], i), inv[i] = fpow(fac[i], Mod - 2);
    rep(i, 1, L) rep(j, 0, L) rep(k, 0, j / 2) 
        dp[i][j] = Inc(dp[i][j], Mul(dp[i - 1][j - 2 * k], Mul(inv[k], inv[k])));
    Q = read();
    while (Q--) {
        n = read(), T = read();
        printf("%d
", Mul(dp[n][T], fac[T]));
    }
    return 0;
}

值得一提的,广义上的正难则反就是从难点的对立面来考虑,比如:具体问题抽象化,抽象问题具体化,区间问题单点化等等。

GO!
原文地址:https://www.cnblogs.com/Go7338395/p/13819394.html