题意:定义函数\(f(A,B) = \sum_{i=1}^n \max(A_i,B_i)\),其中\(A\)和\(B\)都是长度为\(n\)的排列。给出\(n\)和\(k\),问有多少对\((A,B)\)满足\(f(A,B)\geq k\)。对\(10^9 + 7\)取模。

\(n \leq 50\)

首先,可以直接钦定\(A\)为\(1,2...n\)的一个排列,即对于所有\(i\)满足\(A_i = i\),最后答案再乘以\(n!\)。

然后就变成了对\(B\)这一个排列的计数问题。考虑函数\(f\)中有贡献的只有较大值,我们不必计较其中的较小值具体是什么。这启发我们在dp时把较小的数分配到较大的位置,并记录其数量。

因此,我们令状态\(dp_{i,j,k}\)表示当前从\(1\)开始放置了\(i\)个数,其中有\(j\)个数被分配到后面的位置,并且当前得到的函数值为\(k\)。当然,这里的函数值只包括\(\max(A_s,B_s) \leq i\)的值,这样便于转移。同样地,当我们把一个数分配到后面的位置上时,我们不能轻易乘上一个系数(可分配的位置个数),因为分配不同的位置对答案的贡献不同。

那么,对于第\(i+1\)个数以及位置,就有下面这些情况:

  • \(i+1\)放在第\(i+1\)个位置。那么,j不变,k+=i,且只有一种方案。
  • \(i+1\)放在前\(i\)个位置,第\(i+1\)个位置放了小于\(i+1\)的数。那么,j-=1,k+=2*i,且第\(i+1\)个数有\(j\)个位置可放,第\(i+1\)个位置也有\(j\)个数来放。因此有\(j^2\)种方案。
  • \(i+1\)放在前\(i\)个位置,第\(i+1\)个位置放了大于\(i+1\)的数。那么,j不变,k+=i,且第\(i+1\)个数有\(j\)个位置可放,放在第\(i+1\)个位置的数未确定。因此有\(j\)种方案。
  • \(i+1\)放在后面的位置,第\(i+1\)个位置放了小于\(i+1\)的数。那么,j不变,k+=i,且\(i+1\)未确定放在哪个位置,第\(i+1\)个位置有\(j\)个数来放。因此有\(j\)种方案。
  • \(i+1\)放在后面的位置,第\(i+1\)个位置放了大于\(i+1\)的数。那么,j+=1,k不变,且\(i+1\)放在哪里,第\(i+1\)个位置放什么都是为确定的。因此只有一种方案。

时间复杂度\(O(n^4)\)。

#include <bits/stdc++.h>
using namespace std; const int MAXN = 55, MOD = (int)(1e9 + 7);
int dp[2][MAXN][MAXN * MAXN];
class LittleElephantAndPermutationDiv1 {
public:
int getNumber( int N, int K );
};
int LittleElephantAndPermutationDiv1::getNumber(int N, int K) {
int p = 1;
memset(dp,0,sizeof dp);
dp[0][0][0] = 1;
for (int i = 1 ; i <= N ; ++ i, p ^= 1) {
memset(dp[p],0,sizeof dp[p]);
for (int j = 0 ; j < i ; ++ j) {
for (int k = 0 ; k <= 2500 ; ++ k) {
if (!dp[p^1][j][k]) continue;
(dp[p][j][k+i] += dp[p^1][j][k]) %= MOD;
if (j > 0) (dp[p][j-1][k+i+i] += 1ll * j * j * dp[p^1][j][k] % MOD) %= MOD;
if (i < N) (dp[p][j][k+i] += 1ll * j * dp[p^1][j][k] % MOD) %= MOD;
if (i < N) (dp[p][j][k+i] += 1ll * j * dp[p^1][j][k] % MOD) %= MOD;
if (i < N) (dp[p][j+1][k] += dp[p^1][j][k]) %= MOD;
}
}
}
p ^= 1;
int ret = 0;
for (int i = K ; i <= 2500 ; ++ i)
(ret += dp[p][0][i]) %= MOD;
for (int i = 1 ; i <= N ; ++ i)
ret = 1ll * ret * i % MOD;
return ret;
}

小结:这个dp的特色在于确定一个排列,从而同时对位置和值的分配dp,这样可以解决一些较复杂的问题。

【做题】TCSRM592 Div1 500 LittleElephantAndPermutationDiv1——计数&dp的更多相关文章

  1. 【做题】agc008f - Black Radius——计数&讨论&思维

    原文链接 https://www.cnblogs.com/cly-none/p/9794411.html \[ \newcommand{\stif}[2]{\left[ \begin{matrix} ...

  2. 【做题】ZJOI2017仙人掌——组合计数

    原文链接 https://www.cnblogs.com/cly-none/p/ZJOI2017cactus.html 给出一个\(n\)个点\(m\)条边的无向连通图,求有多少种加边方案,使得加完后 ...

  3. 【做题】ECFinal2018 J - Philosophical … Balance——dp

    原文链接 https://www.cnblogs.com/cly-none/p/ECFINAL2018J.html 题意:给出一个长度为\(n\)的字符串\(s\),要求给\(s\)的每个后缀\(s[ ...

  4. 【做题】CF285E. Positions in Permutations——dp+容斥

    题意:求所有长度为\(n\)的排列\(p\)中,有多少个满足:对于所有\(i \,(1 \leq i \leq n)\),其中恰好有\(k\)个满足\(|p_i - i| = 1\).答案对\(10^ ...

  5. 火题大战Vol.0 B 计数DP

    火题大战Vol.0 B 题目描述 \(n\) 个沙茶,被编号 \(1\)~$ n$.排完队之后,每个沙茶希望,自己的相邻的两人只要无一个人的编号和自己的编号相差为 \(1\)(\(+1\) 或\(-1 ...

  6. DP 优化方法大杂烩 & 做题记录 I.

    标 * 的是推荐阅读的部分 / 做的题目. 1. 动态 DP(DDP)算法简介 动态动态规划. 以 P4719 为例讲一讲 ddp: 1.1. 树剖解法 如果没有修改操作,那么可以设计出 DP 方案 ...

  7. [Hdu-5155] Harry And Magic Box[思维题+容斥,计数Dp]

    Online Judge:Hdu5155 Label:思维题+容斥,计数Dp 题面: 题目描述 给定一个大小为\(N*M\)的神奇盒子,里面每行每列都至少有一个钻石,问可行的排列方案数.由于答案较大, ...

  8. DP 做题记录 II.

    里面会有一些数据结构优化 DP 的题目(如 XI.),以及普通 DP. *I. P3643 [APIO2016]划艇 题意简述:给出序列 \(a_i,b_i\),求出有多少序列 \(c_i\) 满足 ...

  9. 【做题】spoj4060 A game with probability——dp

    赛前做题时忽然发现自己概率博弈类dp很弱,心好慌.(获胜概率或最优解期望) 于是就做了这道题,续了特别久. 一开始列dp式子的时候就花了很长时间,首先搞错了两次,然后忘记了根据上一轮dp值直接确定选什 ...

随机推荐

  1. kali linux wmtools安装

    1,选择挂载盘时选择自动检测 2,点击安裝vmware tools安裝 3.tar -xzf 壓縮包名 4../vmware-install.pl 5,reboot

  2. 5.JVM的内存区域划分

    一.JVM介绍 1. 什么是JVM? JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟 ...

  3. html5-超级链接

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  4. hdu5290树形dp

    题意 给了n个点的数 每个点有一个w[i]权值,如果你选择了i这个点那么距离i这个点距离为w[i]的点将被除去,最后问 选则尽量少的点把这n个点全部删除 1<=n<=100000, 0&l ...

  5. 分布式系统ID生成方案

    自增ID 不错,可以限度抑制ID的大小.但需要有一个中心化的节点作为解决原子性问题.可以选用Redis,MySQL,Zookeeper.成本有点高. UUID 分布式,而且唯一!缺点是生产的ID太长. ...

  6. VI编辑器常用命令

    Linux下的文本编辑器有很多种,vi 是最常用的,也是各版本Linux的标配.注意,vi 仅仅是一个文本编辑器,可以给字符着色,可以自动补全,但是不像 Windows 下的 word 有排版功能. ...

  7. 调查显示数据分析已取代Web开发成为第一用例

    一项关于Python的开发者调查显示,编程语言现在主要用于数据分析,取代了之前的第一个用例Web开发. 去年秋天,由Python软件基金会和开发人员工具供应商JetBrains进行,2018 Pyth ...

  8. flask框架----flask中的wtforms使用

    一.简单介绍flask中的wtforms WTForms是一个支持多个web框架的form组件,主要用于对用户请求数据进行验证. 安装: pip3 install wtforms 二.简单使用wtfo ...

  9. jmeter压力测试及抓包

    如何使用jmeter进行分布式压力测试? 1.其他的压力机启动jmeter-server 2.在主控机jmeter的配置文件jmeter.properties里面找到,remote_hosts=xx, ...

  10. c#md5加密的简单用法

    using System.Security.Cryptography; //MD5 md5 = MD5.Create(); MD5 md5 = new MD5CryptoServiceProvider ...