一定要注意Topcoder的提交机制

Links: 原题地址 Vjudge

Solution

这道题思维比较巧妙。 一看就基本知道是一个Dp题。

首先转换一下,用列而不是行来设第一维的状态,因为每列只有放或不放两种状态。行的受力情况很复杂,这里啊

那么对于每一列,到了要分配Left的时候我们再把前面的列分配过来。

Right的时候,我们就反其道而行之,把Right贮存下来,然后之后每一个格子都考虑要不要分配一次。

这样Dp状态就显而易见:\(Dp[i][j][k]\)表示前i列中有j列空余kRight没有处理的方案数。

然后就比较容易写出dp方程.下面是废话:

先分类。这一列可以对Left Right造成影响. 也可以不造成影响(放在没用的地方或完全不让放)

因为Left,Right对状态影响很大,所以分成两个式子。

notice:在考虑问题的时候中间问题的中间态如果不是很重要的话,整体都可以略过

具体见代码

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
#define drep(i, a, b) for(int i = (a), i##_end_ = (b); i >= i##_end_; --i)
#define clar(a, b) memset((a), (b), sizeof(a))
#define debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
int read() {
char ch = getchar();
int x = 0, flag = 1;
for (;!isdigit(ch); ch = getchar()) if (ch == '-') flag *= -1;
for (;isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
return x * flag;
}
void write(int x) {
if (x < 0) putchar('-'), x = -x;
if (x >= 10) write(x / 10);
putchar(x % 10 + 48);
} const int Maxn = 59, Maxm = 209, Mod = 1e9 + 7;
class TaroCheckers {
public:
LL C[Maxm * 10][Maxm * 10], dp[Maxm][Maxm][Maxn], fac[Maxm * 10];
LL L[Maxm], R[Maxm];
void calcMath(LL m) {
C[0][0] = fac[0] = 1;
rep (i, 1, m) fac[i] = fac[i - 1] * i % Mod;
rep (i, 1, m) {
C[i][0] = C[i][i] = 1;
rep (j, 1, i - 1) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % Mod;
}
}
int getNumber(vector <int> Left, vector <int> Right, int m) {
LL n = (LL)Left.size();
calcMath(n + m); clar(dp, 0); clar(L, 0), clar(R, 0);
rep (i, 0, n - 1) ++L[Left[i]], ++R[m - Right[i] + 1];
dp[0][0][0] = 1; LL res = 0;
rep (i, 0, m - 1) {
LL cnt1 = L[i + 1], cnt2 = R[i + 1];
rep (j, 0, i)
rep (k, 0, n)
if (dp[i][j][k]) {
if (j + 1 >= cnt1) (dp[i + 1][j + 1 - cnt1][k + cnt2] += dp[i][j][k] * C[j + 1][cnt1] % Mod * fac[cnt1] % Mod) %= Mod;
if (j >= cnt1) (dp[i + 1][j - cnt1][k + cnt2] += dp[i][j][k] * C[j][cnt1] % Mod * fac[cnt1] * (res - cnt2 + 1) % Mod) %= Mod;
if (j >= cnt1 && k + cnt2 - 1 >= 0) (dp[i + 1][j - cnt1][k + cnt2 - 1] += dp[i][j][k] * C[j][cnt1] % Mod * fac[cnt1] % Mod * (k + cnt2) % Mod) %= Mod;
}
res += cnt1 - cnt2;
} return dp[m][0][0];
}
};

[SRM613~] TaroCheckers的更多相关文章

随机推荐

  1. Excel小tips - 如何实现多列成绩统一排名

    本文参考:http://mp.weixin.qq.com/s/XR49hyG9Cods7rOcsM-tRg 如果有以下数据文件,需要进行成绩排名. 第一步:先在成绩列后边添加一列,用来显示名次.如下: ...

  2. 表皮囊肿?wtf

    https://baike.baidu.com/item/%E8%A1%A8%E7%9A%AE%E5%9B%8A%E8%82%BF/7852024?fr=aladdin

  3. ubuntu 16.04上安装php5.6

    php --ini 按下面的步骤,在ubuntu 16.04上面安装成功了 php5.6 dpkg -l | grep php| awk '{print $2}' |tr "\n" ...

  4. 一处折腾笔记:Android内嵌html5加入原生微信分享的解决的方法

    有一段时间没有瞎折腾了. 这周一刚上班萌主过来反映说:微信里面打开聚客宝.分享功能是能够的(这里是用微信自身的js-sdk实现的).可是在android应用里面打开点击就没反应了:接下来狡猾的丁丁在产 ...

  5. 一天教你入门struts2

    写在前面 自己也是一个java和java web的菜鸟.之前没有接触过java web方面的开发 想通过一个小项目,来熟悉struts2的开发流程 一个有趣的想法源于教研室项目上的一个功能实现–自己主 ...

  6. Office WORD如何去掉目录的背景灰色

    有人说鼠标点击空白的地方灰色就自动散掉了,但是我点击并没有散掉 鼠标选中有灰色背景的文字,点击格式-边框和底纹,点击无填充颜色,并应用于文字. O了

  7. Java静态分派与动态分派(二)

    方法调用并不等于方法执行,方法调用阶段唯一的任务就是确定被调用方法的版本(即调用哪一个方法),暂时还不涉及方法内部的具体运行过程. 在程序运行时,进行方法调用是最普遍.最频繁的操作,但是Class文件 ...

  8. linux之rsync远程数据同步备份

    rsync服务是一种高效的远程数据备份的工具,该服务的port号为873, 是Liunx下的一种非独立服务.由xinetd超级服务管理,取代监听873port. 长处: 1.rsync能够利用ssh和 ...

  9. 【转】TestNG中的并发(多线程)

    优势 并行(多线程)技术在软件术语里被定义为软件.操作系统或者程序可以并行地执行另外一段程序中多个部分或者子组件的能力 多线程方式拥有很大的优势: 1). 减少测试运行时间 如果测试集里包含了大量的用 ...

  10. soapUI系列之—-03 Groovy脚本常用方法2

    ------Groovy脚本常用方法 1.解析Json数据脚本 //groovy读取json的方式很简单,re.body.businessinfo.c2rate读取c2rate对应的值 import ...