\(\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 模拟赛」打拳的更多相关文章

  1. 「NOIP模拟赛」数位和乘积(dp,高精)

    统计方案数,要么组合数,要么递推(dp)了. 这是有模拟赛历史以来爆炸最狠的一次 T1写了正解,也想到开long long,但是开错了地方然后数组开大了结果100->0 T3看错题本来简单模拟又 ...

  2. 「NOIP模拟赛」Round 3

    Tag 计数+LIS, 二分+ST表, 计数+记搜 A. 改造二叉树 Description 题面 Solution 如果目标序列非严格递增,或者说目标序列是不下降的,那么答案就是 \(n\) 减去最 ...

  3. 「NOIP模拟赛」Round 2

    Tag 递推,状压DP,最短路 A. 篮球比赛1 题面 \(Milky\ Way\)的代码 #include <cstdio> const int N = 2000, xzy = 1e9 ...

  4. 计蒜客NOIP模拟赛6 D1T1Diamond-square

    Diamond-square 算法是一种能够用于生成噪声的算法,现在我们考虑这个算法的一个变种. 你有一个 2^n\times 2^n2​n​​×2​n​​ 的网格,一共有 (2^n+1)^2(2​n ...

  5. 计蒜客NOIP模拟赛4 D2T1 鬼脚图

    鬼脚图,又称画鬼脚,在日本称作阿弥陀签,是一种经典游戏,也是一种简易的决策方法,常常用来抽签或决定分配组合. 下图就是一张鬼脚图,其包含若干条竖线和若干条横线.请注意,横线只能水平连接相邻的两条竖线, ...

  6. 计蒜客NOIP模拟赛4 D1T2小X的密室

    小 X 正困在一个密室里,他希望尽快逃出密室. 密室中有 N 个房间,初始时,小 X 在 1 号房间,而出口在 N 号房间. 密室的每一个房间中可能有着一些钥匙和一些传送门,一个传送门会单向地创造一条 ...

  7. 计蒜客 NOIP模拟赛(3) D1T1火山喷发

    火山喷发对所有附近的生物具有毁灭性的影响.在本题中,我们希望用数值来模拟这一过程. 在环境里有 nnn 个生物分别具有 A1,A2,⋯,An​​点生命值,一次火山喷发总计 M轮,每轮造成 1点伤害,等 ...

  8. 计蒜客NOIP模拟赛(2) D2T3 银河战舰

    [问题描述]    瑞奥和玛德利德是非常好的朋友.瑞奥平时的爱好是吹牛,玛德利德的爱好是戳穿瑞奥吹的牛.    这天瑞奥和玛德利德来到了宇宙空间站,瑞奥向玛德利德炫耀这个空间站里所有的银河战舰都是自己 ...

  9. 计蒜客NOIP模拟赛5 D1T1 机智的 AmyZhi

    那年一个雨季,AmyZhi 在校门外弯身买参考书. 这时 SiriusRen 走过来,一言不合甩给她一道“自认为”很难的题: --------------- 给你一个数字 NN(NN 的范围是 11  ...

随机推荐

  1. 详解nginx的请求限制(连接限制和请求限制)

    https://www.jb51.net/article/143682.htm 一,背景 我们经常会遇到这种情况,服务器流量异常,负载过大等等.对于大流量恶意的攻击访问,会带来带宽的浪费,服务器压力, ...

  2. next中layout

    layout是页面模板,主要是为了做到无论在任何页面都会显示的内容,例如头部header,或者nav导航,页脚等固定页面.nuxt配置以及layout具体参考(https://cloud.tencen ...

  3. PPT2010制作翻牌动画

    原文: https://www.toutiao.com/i6492653280676545037/ 新建一张空白幻灯片 选择"插入"选项卡,"插入"功能组,&q ...

  4. 【Java常用类】String

    文章目录 String String实例化的方式 方式一:通过字面量定义 方式二:new + 构造器的方式 String s = new String("abc")方式创建对象,在 ...

  5. Java 各个版本中的新特性

    新特性你知道多少? Java 8 Lambda 表达式 接口增加默认方法等 方法引用 流 Stream Java 9 模块系统 交互式工具jshell .of() 创建不可变集合 接口支持私有方法 更 ...

  6. 学习javaScript必知必会(6)~类、类的定义、prototype 原型、json对象

    一.定义类:使用的是funciton,因为在js中没有定义类的class语句,只有function. ■ 举例: //定义一个Person类(通过类的无参构造函数定义类) function Perso ...

  7. 1121day-户别确认

    1.Addinfor.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" ...

  8. Sentry 开发者贡献指南 - 浏览器 SDK 集成测试

    Sentry 的浏览器 SDK 的集成测试在内部使用 Playwright.这些测试在 Chromium.Firefox 和 Webkit 的最新稳定版本上运行. https://playwright ...

  9. 第02讲:Flink 入门程序 WordCount 和 SQL 实现

    我们右键运行时相当于在本地启动了一个单机版本.生产中都是集群环境,并且是高可用的,生产上提交任务需要用到flink run 命令,指定必要的参数. 本课时我们主要介绍 Flink 的入门程序以及 SQ ...

  10. gin框架中的中间件

    全局中间件 所有请求都经过此中间件 中间件中设置值 func MiddleWare() gin.HandlerFunc { return func(context *gin.Context) { t ...