【做题】TCSRM592 Div1 500 LittleElephantAndPermutationDiv1——计数&dp
题意:定义函数\(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的更多相关文章
- 【做题】agc008f - Black Radius——计数&讨论&思维
原文链接 https://www.cnblogs.com/cly-none/p/9794411.html \[ \newcommand{\stif}[2]{\left[ \begin{matrix} ...
- 【做题】ZJOI2017仙人掌——组合计数
原文链接 https://www.cnblogs.com/cly-none/p/ZJOI2017cactus.html 给出一个\(n\)个点\(m\)条边的无向连通图,求有多少种加边方案,使得加完后 ...
- 【做题】ECFinal2018 J - Philosophical … Balance——dp
原文链接 https://www.cnblogs.com/cly-none/p/ECFINAL2018J.html 题意:给出一个长度为\(n\)的字符串\(s\),要求给\(s\)的每个后缀\(s[ ...
- 【做题】CF285E. Positions in Permutations——dp+容斥
题意:求所有长度为\(n\)的排列\(p\)中,有多少个满足:对于所有\(i \,(1 \leq i \leq n)\),其中恰好有\(k\)个满足\(|p_i - i| = 1\).答案对\(10^ ...
- 火题大战Vol.0 B 计数DP
火题大战Vol.0 B 题目描述 \(n\) 个沙茶,被编号 \(1\)~$ n$.排完队之后,每个沙茶希望,自己的相邻的两人只要无一个人的编号和自己的编号相差为 \(1\)(\(+1\) 或\(-1 ...
- DP 优化方法大杂烩 & 做题记录 I.
标 * 的是推荐阅读的部分 / 做的题目. 1. 动态 DP(DDP)算法简介 动态动态规划. 以 P4719 为例讲一讲 ddp: 1.1. 树剖解法 如果没有修改操作,那么可以设计出 DP 方案 ...
- [Hdu-5155] Harry And Magic Box[思维题+容斥,计数Dp]
Online Judge:Hdu5155 Label:思维题+容斥,计数Dp 题面: 题目描述 给定一个大小为\(N*M\)的神奇盒子,里面每行每列都至少有一个钻石,问可行的排列方案数.由于答案较大, ...
- DP 做题记录 II.
里面会有一些数据结构优化 DP 的题目(如 XI.),以及普通 DP. *I. P3643 [APIO2016]划艇 题意简述:给出序列 \(a_i,b_i\),求出有多少序列 \(c_i\) 满足 ...
- 【做题】spoj4060 A game with probability——dp
赛前做题时忽然发现自己概率博弈类dp很弱,心好慌.(获胜概率或最优解期望) 于是就做了这道题,续了特别久. 一开始列dp式子的时候就花了很长时间,首先搞错了两次,然后忘记了根据上一轮dp值直接确定选什 ...
随机推荐
- 软工网络15团队作业4——Alpha阶段敏捷冲刺5.0
1.每天举行站立式会议,提供当天站立式会议照片一张. 2.项目每个成员的昨天进展.存在问题.今天安排. 成员 昨天已完成 今天计划完成 郭炜埕 完善新建话题界面 实现前端各界面的跳转连接 郑晓丽 进行 ...
- lua学习之循环求一个数的阶乘
--第3题 利用循环求n的阶乘 --参数检查是否是自然数 function IsNaturalNumber(n) ~= )then return false else return true end ...
- 【转】robotFramework 与testlink集成
场景: robotframework 执行完用例之后,将执行结果报至testlink. 方案1: 通过TestLink-API-Python-client中的RF关键字 每条用例执行完成之后根据状态进 ...
- JavaScript--将秒数换算成时分秒
getTime() 返回距 1970 年 1 月 1 日之间的毫秒数 new Date(dateString) 定义 Date 对象的一种方式 <!DOCTYPE html> <h ...
- jQuery属性--addClass()和removeClass()
addClass(class|fn) 概述 为每个匹配的元素添加指定的类名 参数 class 一个或多个要添加到元素中的CSS类名,请用空格分开: function(index, class) ...
- 【2017-2-20】C#运算符
运算符分类: 1.算术运算符 ⑴+ - * / %(取余,模) /3; Console.Write(d); Console.ReadLine(); 则输出结果为“3”,因为10和3都是int型,dec ...
- numpy数学数据处理
数学和统计方法 sum 对数组中全部或某轴向的元素求和.零长度的数组的sum为0. mean 算术平均数.零长度的数组的mean为NaN. import numpy as np import nump ...
- Linux基础命令---显示主机名hostname
hostname hostname指令用于设置或者显示系统主机名,没有任何参数就会返回gethostname()函数的返回值.使用hostname指令之后,主机名会立马被修改,但是重启系统之后就失效了 ...
- Linux服务器---流量监控ntop
Ntop Ntop 是一款类似于sniffer的流量监控工具,它显示出的流量信息比mrtg更加详细. 1 .安装一些依赖软件 [root@localhost bandwidthd]# yum ins ...
- scrapy 自定义图片路径保存,并存到数据库中
scrapy中有个自带的pipeline工具,ImagesPipeline,可以专门用来储存图片到本地. 但默认储存地址无法配置,所以我们需要写一个自己的pipeline用于储存图片. 先分析一下我们 ...