Solution -「牛客 NOIP 模拟赛」打拳
\(\mathcal{Description}\)
现 \(2^n\) 个人进行淘汰赛,他们的战力为 \(1\sim 2^n\),战力强者能战胜战力弱者,但是战力在集合 \(\{a_m\}\) 里的人可以放水输给战力为 \(1\) 的人。求让 \(1\) 获胜的初始安排,并要求 \(1\) 依次战胜的人的战力序列的 LIS 长度不小于 \(l\)。
\(m\le16\),\(l\le n\le9\)。
\(\mathcal{Solution}\)
出题人你为什么不把题意写在题面里啊?
第一种方法:枚举 \(1\) 战胜的 \(n\) 个人的战力大小关系 DP,非常轻松,这里不提。
第二种方法需要灵活地联系 LIS 的各种求法。结合方法一的一些实现细节,可以发现这样维护 LIS 非常合理:按值从小到大将数加入序列,维护每个长度的 LIS 的最前结尾位置。首先将 \(\{a_m\}\) 升序排列,定义状态 \(f(i,S,T)\) 表示考虑了 \(\{a_m\}\) 中前 \(i\) 个数;\(1\) 的战胜序列中集合 \(S\) 内的位置已经使用;其中集合 \(T\subseteq S\) 内的位置是最优 LIS 的结尾。组合数计算在竞标赛树里加一棵子树的方案即可转移。相当于一个 DP 套 DP。复杂度 \(\mathcal O(mn3^n)\)。
所以写这篇题解的目的是总结一下求 LIS 的方法:
- \(f(i)\) 表示以 \(i\) 结尾的最长 LIS。优点:好想好写。
- \(f(i)\) 表示(考虑了前缀位置后)LIS 长度为 \(i\) 的最小结尾数。优点:可将值记入状态。
- \(f(i)\) 表示(考虑了前若干小的值后)LIS 长度为 \(i\) 的最小结尾位置。优点:可将位置记入状态。
\(\mathcal{Code}\)
/*~Rainybunny~*/
#include <bits/stdc++.h>
#define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )
const int MAXN = 9, MAXM = 16;
int n, m, l, P, a[MAXM + 5], f[2][1 << MAXN][1 << MAXN];
int fac[1 << MAXN | 5], ifac[1 << MAXN | 5];
inline void chkmax( int& u, const int v ) { u < v && ( u = v ); }
inline int mul( const int u, const int v ) { return 1ll * u * v % P; }
inline int add( int u, const int v ) { return ( u += v ) < P ? u : u - P; }
inline void addeq( int& u, const int v ) { ( u += v ) >= P && ( u -= P ); }
inline int mpow( int u, int v ) {
int ret = 1;
for ( ; v; u = mul( u, u ), v >>= 1 ) ret = mul( ret, v & 1 ? u : 1 );
return ret;
}
inline void init() {
fac[0] = 1;
rep ( i, 1, 1 << n ) fac[i] = mul( i, fac[i - 1] );
ifac[1 << n] = mpow( fac[1 << n], P - 2 );
per ( i, ( 1 << n ) - 1, 0 ) ifac[i] = mul( i + 1, ifac[i + 1] );
}
inline int bino( const int u, const int v ) {
return v < 0 || u < v ? 0 : mul( fac[u], mul( ifac[v], ifac[u - v] ) );
}
int main() {
freopen( "punch.in", "r", stdin );
freopen( "punch.out", "w", stdout );
scanf( "%d %d %d %d", &n, &m, &l, &P ), init();
rep ( i, 1, m ) scanf( "%d", &a[i] );
std::sort( a + 1, a + m + 1 );
f[0][0][0] = 1;
rep ( i, 1, m ) {
int sta = ~i & 1;
rep ( S, 0, ( 1 << n ) - 1 ) for ( int T = S; ; T = ( T - 1 ) & S ) {
int& cur = f[sta][S][T];
if ( !cur && !T ) break;
if ( !cur ) continue;
addeq( f[!sta][S][T], cur );
rep ( j, 0, n - 1 ) if ( ~S >> j & 1 ) {
int c = mul( fac[1 << j],
bino( a[i] - 2 - S, ( 1 << j ) - 1 ) );
if ( !c ) continue;
addeq( f[!sta][S | 1 << j][( T >> j ?
( T >> j & ( T >> j ) - 1 ) << j |
T & ( 1 << j ) - 1 : T ) | 1 << j], mul( cur, c ) );
}
cur = 0;
if ( !T ) break;
}
}
int ans = 0;
rep ( T, 0, ( 1 << n ) - 1 ) if ( __builtin_popcount( T ) >= l ) {
addeq( ans, f[m & 1][( 1 << n ) - 1][T] );
}
printf( "%d\n", mul( ans, 1 << n ) );
return 0;
}
Solution -「牛客 NOIP 模拟赛」打拳的更多相关文章
- 「NOIP模拟赛」数位和乘积(dp,高精)
统计方案数,要么组合数,要么递推(dp)了. 这是有模拟赛历史以来爆炸最狠的一次 T1写了正解,也想到开long long,但是开错了地方然后数组开大了结果100->0 T3看错题本来简单模拟又 ...
- 「NOIP模拟赛」Round 3
Tag 计数+LIS, 二分+ST表, 计数+记搜 A. 改造二叉树 Description 题面 Solution 如果目标序列非严格递增,或者说目标序列是不下降的,那么答案就是 \(n\) 减去最 ...
- 「NOIP模拟赛」Round 2
Tag 递推,状压DP,最短路 A. 篮球比赛1 题面 \(Milky\ Way\)的代码 #include <cstdio> const int N = 2000, xzy = 1e9 ...
- 计蒜客NOIP模拟赛6 D1T1Diamond-square
Diamond-square 算法是一种能够用于生成噪声的算法,现在我们考虑这个算法的一个变种. 你有一个 2^n\times 2^n2n×2n 的网格,一共有 (2^n+1)^2(2n ...
- 计蒜客NOIP模拟赛4 D2T1 鬼脚图
鬼脚图,又称画鬼脚,在日本称作阿弥陀签,是一种经典游戏,也是一种简易的决策方法,常常用来抽签或决定分配组合. 下图就是一张鬼脚图,其包含若干条竖线和若干条横线.请注意,横线只能水平连接相邻的两条竖线, ...
- 计蒜客NOIP模拟赛4 D1T2小X的密室
小 X 正困在一个密室里,他希望尽快逃出密室. 密室中有 N 个房间,初始时,小 X 在 1 号房间,而出口在 N 号房间. 密室的每一个房间中可能有着一些钥匙和一些传送门,一个传送门会单向地创造一条 ...
- 计蒜客 NOIP模拟赛(3) D1T1火山喷发
火山喷发对所有附近的生物具有毁灭性的影响.在本题中,我们希望用数值来模拟这一过程. 在环境里有 nnn 个生物分别具有 A1,A2,⋯,An点生命值,一次火山喷发总计 M轮,每轮造成 1点伤害,等 ...
- 计蒜客NOIP模拟赛(2) D2T3 银河战舰
[问题描述] 瑞奥和玛德利德是非常好的朋友.瑞奥平时的爱好是吹牛,玛德利德的爱好是戳穿瑞奥吹的牛. 这天瑞奥和玛德利德来到了宇宙空间站,瑞奥向玛德利德炫耀这个空间站里所有的银河战舰都是自己 ...
- 计蒜客NOIP模拟赛5 D1T1 机智的 AmyZhi
那年一个雨季,AmyZhi 在校门外弯身买参考书. 这时 SiriusRen 走过来,一言不合甩给她一道“自认为”很难的题: --------------- 给你一个数字 NN(NN 的范围是 11 ...
随机推荐
- let var const 区别
let es6 语法 let是作用域是块级的,即{}内的范围 如果未声明变量就使用的话,报错ReferenceError,而var则会报错undefined(不存在变量提升) 只要块级作用域内存在le ...
- 虚拟机上CentOS7网络配置
如果图片损坏:点击链接:https://www.toutiao.com/i6493449418249863693/ 设置网络 首先打开虚拟网络编辑器 权限打开 选择NAT模式,设置IP 应用确定之后, ...
- vscode 前端好用插件汇总
本篇文章根据实际开发中使用的扩展插件,结合<精选!15 个必备的 VSCode 插件(前端类)>.<vscode 插件推荐 - 献给所有前端工程师(2017.8.18更新)>中 ...
- POJ prime distance
https://oj.shiyancang.cn/Problem/781.html 素数距离,数据范围21亿,如果用素数筛存,并且进行做的话,按照x/lnx计算会是一个非常恐怖的复杂度.确定要做什么, ...
- 【Maven】maven 插件开发实战
前言 众所周知,maven 实质上是一个插件执行框架,所有的工作都是通过插件完成的.包括我们日常使用到的类似 install.clean.deploy.compiler...这些命令,其实底层都是一个 ...
- Docker之Docker Machine已弃用
作为刚开始学习docker的新手,从网上查询文档无疑是最快的学习捷径,但是这次在docker翻车了,困扰了整整三天,特记录一下. 一般我们使用docker for windows安装,一路往下点直至安 ...
- 通过HTML+CSS+JavaScript实现鼠标移动到页面顶部导航栏出现,如果移出导航栏3秒又隐藏起来,而且不受滚动条影响(二)
通过HTML+CSS+JavaScript实现鼠标移动到页面顶部导航栏出现,如果移出导航栏3秒又隐藏起来,而且不受滚动条影响(二) 效果:默认一直隐藏导航栏,当滚动条滚到超过300px按钮出现,点击回 ...
- Solon Web 开发,七、视图模板与Mvc注解
Solon Web 开发 一.开始 二.开发知识准备 三.打包与运行 四.请求上下文 五.数据访问.事务与缓存应用 六.过滤器.处理.拦截器 七.视图模板与Mvc注解 八.校验.及定制与扩展 九.跨域 ...
- 源代码管理git地址从http改为https,提交400错误
推送400错误 cmd 执行 git config --global http.sslVerify false 推送地址,修改http 为 https 就可以正常提交了
- 集合框架-TreeSet-Comparator比较器
1 package cn.itcast.p5.treeset.demo; 2 3 import java.util.Iterator; 4 import java.util.TreeSet; 5 6 ...