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

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

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

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

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

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

\[dp_{i, j} = \sum\limits_{k = 0} ^ {\lfloor \frac{j}{2} \rfloor} dp_{i - 1, j - 2 \times k} \times \dbinom{T - j + 2 \times k}{k} \times \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\n", Mul(dp[n][T], fac[T]));
}
return 0;
}

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

SP19149 INS14H - Virus Revisited的更多相关文章

  1. Virus.Win32.Virlock.b分析

    0x00 样本说明 分析样本是被0b500d25f645c0b25532c1e3c9741667的样本感染得到.感染前的文件是Tcpview.exe,一款windows网络连接查看工具. 感染前后文件 ...

  2. csuoj 1394: Virus Replication

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1394 1394: Virus Replication Time Limit: 1 Sec  Mem ...

  3. sublimeText jsformat 插件被当做病毒 virus

    最近在个只可往他里面发邮件,不能往外上任何互联网的地方工作,用 sublimetext 要装个sublime 插件 jsformat 十分麻烦.用gmail邮箱发总是报病毒. 最后挨个尝试,发现是 j ...

  4. hdu 3695:Computer Virus on Planet Pandora(AC自动机,入门题)

    Computer Virus on Planet Pandora Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 256000/1280 ...

  5. HDU 3695 Computer Virus on Planet Pandora(AC自动机模版题)

    Computer Virus on Planet Pandora Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 256000/1280 ...

  6. hdu ----3695 Computer Virus on Planet Pandora (ac自动机)

    Computer Virus on Planet Pandora Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 256000/1280 ...

  7. 最近碰到了一个病毒木马:virus.win32.ramnit.B

    由于 使用了 简单游 平台上的挂机工具: 番茄-自动人机对战免费版1217  ,使用了很久,头段时间家里电脑 360提示有病毒,本来我一直忽略的,但 我扫描了一下,大量的这个木马,于是 吧 简单游卸载 ...

  8. ZOJ 3430 Detect the Virus

    传送门: Detect the Virus                                                                                ...

  9. HDU 3695 / POJ 3987 Computer Virus on Planet Pandora(AC自动机)(2010 Asia Fuzhou Regional Contest)

    Description Aliens on planet Pandora also write computer programs like us. Their programs only consi ...

随机推荐

  1. 【python】PyQt5 QAction 添加点击事件

    def test(): #your function ui.yourQActionName.triggered.connect(lambda:test()) #添加lambda: 就不报错了

  2. Log4j使用的方法

    一.什么是log4j Log4J是Apache的一个开放源代码的项目.通过使用Log4J,程序员可以控制日志信息输送的目的地,包括控制台,文件,GUI组件和NT事件记录器,也可以控制每一条日志的输出格 ...

  3. Categorical Reparameterization with Gumbel-Softmax

    目录 概 主要内容 Gumbel distribution Jang E., Gu S. and Poole B. Categorical reparameterization with gumbel ...

  4. Python pyecharts绘制词云图

    一.pyecharts绘制词云图WordCloud.add()方法简介 WordCloud.add()方法简介 add(name,attr,value, shape="circle" ...

  5. 解决Web开发HTML页面中footer保持在页面底部问题

    如图所示如何实现footer在内容不足或者浏览器窗口变大变小的时候一直保持在底部呢?请看如下两种解决方案. 第一种方案: footer高度固定+绝对定位 (兼容性比较好完美兼容IE8+)思路:foot ...

  6. JUC之多线程锁问题

    多线程锁 8种问题锁状态: 该部分全部围绕的是以下内容并结合相应的例子:synchronized实现同步的基础:Java中每个对象都可以作为锁. 具体表现为以下三种形式:(之前只是简单的了解) 对于普 ...

  7. APICloud超实用经验分享——平台功能

    从2016年开始使用APICloud进行app项目开发,到现在也有五六年了.在此过程中伴随着APICloud一起成长,踩过一些坑,自己的技术也提升不少.在APICloud 推出avm框架一年之后,ID ...

  8. Linux 进程调度

    线程状态(context) 程序计数器(Program Counter),它表示当前线程执行指令的位置. 保存变量的寄存器. 程序的Stack.通常来说每个线程都有属于自己的Stack,Stack记录 ...

  9. mysql数据库忘记root密码怎么办?

    mysql数据库忘记root密码怎么破解和修改 1.停止数据库的运行 [root@localhost ~]# /etc/init.d/mysqld stop 或者[root@localhost ~]# ...

  10. xshell 所选的用户密钥未在远程主机上注册;无法加载密钥

    他山之石 https://zhuanlan.zhihu.com/p/92528287 安全起见,服务器最近的安全策略准备进行更改,逐渐由原来的密码登录更换为密钥登录认证. 于是今天把服务器上的id_r ...