ARC093F Dark Horse 容斥原理+DP
题目传送门
https://atcoder.jp/contests/arc093/tasks/arc093_d
题解
由于不论 \(1\) 在哪个位置,一轮轮下来,基本上过程都是相似的,所以不妨假设 \(1\) 在第 \(1\) 个位置。
那么,\(1\) 将以此遇到的对手是 \(p_2, \min\{p_3, p_4\}, \min\{p_5, p_6, p_7, p_8\}, \cdots\)。
令这些数分别为 \(b_0, b_1, \cdots\),其中 \(b_i = \min \limits_{j=2^i + 1}^{2^{j+1}} p_j\),长度为 \(2^i\)。满足题意的 \(b\) 中的任何一个数均没有在 \(a\) 中出现过。
考虑容斥。对于集合 \(S\),需要求出 \(\forall i \in S\),有 \(b_i\) 是 \(a\) 中元素的方案数。
可以使用 dp 来实现。为了方便计数,将 \(a\) 从大到小排序。令 \(dp[i][S]\) 表示集合 \(S\) 中的 \(b\) 值均出现在 \(a\) 中前 \(i\) 个数的方案数。(不考虑没有在 \(a\) 中出现的那些 \(b\) 中的元素)
第一种转移是不选第 \(i\) 个数,转移方法是 \(dp[i][S] \to dp[i+1][S]\);
第二种转移,枚举一个没有在 \(S\) 中出现的位置 \(j\),则可以转移 \(dp[i][S] \cdot \binom{les}{2^j-1} \cdot (2^j)! \to dp[i+1][S \cup \{j\}]\)。
最后,计算集合 \(S\) 的实际方案数的时候,由于之前的 dp 没有考虑那些没有在 \(a\) 中出现的 \(b\),所以还需要乘上 \((2^n - 1 - S)!\)。
下面是代码。状态数一共 \(O(mS)\),转移 \(O(n)\),总时间复杂度 \(O(nmS)\)。
#include<bits/stdc++.h>
#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back
template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b , 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b , 1 : 0;}
typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii;
template<typename I>
inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
}
#define lowbit(x) ((x) & -(x))
const int N = 20;
const int M = (1 << 16) + 7;
const int P = 1e9 + 7;
int n, m, S;
int a[N], dp[N][M];
int inv[M], fac[M], ifac[M];
inline int smod(int x) { return x >= P ? x - P : x; }
inline void sadd(int &x, int y) { x += y; x >= P ? x -= P : x; }
inline int fpow(int x, int y) {
int ans = 1;
for (; y; y >>= 1, x = (ll)x * x % P) if (y & 1) ans = (ll)ans * x % P;
return ans;
}
inline void ycl(int n) {
fac[0] = 1; for (int i = 1; i <= n; ++i) fac[i] = (ll)fac[i - 1] * i % P;
inv[1] = 1; for (int i = 2; i <= n; ++i) inv[i] = (ll)(P - P / i) * inv[P % i] % P;
ifac[0] = 1; for (int i = 1; i <= n; ++i) ifac[i] = (ll)ifac[i - 1] * inv[i] % P;
}
inline int C(int x, int y) {
if (x < y) return 0;
return (ll)fac[x] * ifac[y] % P * ifac[x - y] % P;
}
inline void DP() {
S = (1 << n) - 1;
dp[0][0] = 1;
for (int i = 0; i < m; ++i) {
for (int s = 0; s <= S; ++s) {
int les = S + 1 - a[i + 1] - s;
sadd(dp[i + 1][s], dp[i][s]);
for (int j = 0; j < n; ++j) if (!((s >> j) & 1))
sadd(dp[i + 1][s | (1 << j)], (ll)dp[i][s] * C(les, (1 << j) - 1) % P * fac[1 << j] % P);
// dbg("dp[%d][%d] = %d\n", i, s, dp[i][s]);
}
}
}
inline void work() {
ycl(1 << n);
DP();
int ans = 0;
for (int i = 0; i <= S; ++i) {
int cnt = 0, s = i;
while (s) ++cnt, s -= lowbit(s);
if (cnt & 1) sadd(ans, P - (ll)dp[m][i] * fac[S - i] % P);
else sadd(ans, (ll)dp[m][i] * fac[S - i] % P);
// dbg("dp[%d][%d] = %d, cnt = %d, %lld\n", m, i, dp[m][i], cnt, (ll)dp[m][i] * fac[S - i] % P);
}
ans = (ll)ans * (S + 1) % P;
printf("%d\n", ans);
}
inline void init() {
read(n), read(m);
for (int i = 1; i <= m; ++i) read(a[i]);
std::reverse(a + 1, a + m + 1);
}
int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}
ARC093F Dark Horse 容斥原理+DP的更多相关文章
- ARC093F Dark Horse 【容斥,状压dp】
题目链接:gfoj 神仙计数题. 可以转化为求\(p_1,p_2,\ldots,p_{2^n}\),使得\(b_i=\min\limits_{j=2^i+1}^{2^{i+1}}p_j\)都不属于\( ...
- arc093F Dark Horse
我们可以假设1的位置在1,并且依次与右边的区间合并.答案最后乘上2^n即可. 那么需要考虑1所在的区间与另一个区间合并时,另一个区间的最小值不能为特殊的. 直接求解很难,考虑容斥,钦定在哪几个位置必定 ...
- [AtCoder ARC093F]Dark Horse
题目大意:有$2^n$个人,每相邻的两个人比赛一次.令两个人的编号为$a,b(a\leqslant b)$,若$a\neq 1$,则$a$的人获胜:否则若$b\in S$则$b$获胜,不然$1$获胜. ...
- 【arc093f】Dark Horse(容斥原理,动态规划,状态压缩)
[arc093f]Dark Horse(容斥原理,动态规划,状态压缩) 题面 atcoder 有 \(2^n\) 名选手,编号为 \(1\) 至 \(2^n\) .现在这 \(2^n\) 名选手将进行 ...
- ARC 093 F Dark Horse 容斥 状压dp 组合计数
LINK:Dark Horse 首先考虑1所在位置. 假设1所在位置在1号点 对于此时剩下的其他点的方案来说. 把1移到另外一个点 对于刚才的所有方案来说 相对位置不变是另外的方案. 可以得到 1在任 ...
- Atcoder Regular Contest 093 D - Dark Horse(组合数学+状压 dp)
Atcoder 题面传送门 & 洛谷题面传送门 常规题,简单写写罢((( 首先 \(1\) 的位置是什么不重要,我们不妨钦定 \(1\) 号选手最初就处在 \(1\) 号位置,最后答案乘个 \ ...
- [CF245H] Queries for Number of Palindromes (容斥原理dp计数)
题目链接:http://codeforces.com/problemset/problem/245/H 题目大意:给你一个字符串s,对于每次查询,输入为一个数对(i,j),输出s[i..j]之间回文串 ...
- 2018.07.13 [HNOI2015]落忆枫音(容斥原理+dp)
洛谷的传送门 bzoj的传送门 题意简述:在DAG中增加一条有向边,然后询问新图中一共 有多少个不同的子图为"树形图". 解法:容斥原理+dp,先考虑没有环的情况,经过尝试不难发现 ...
- TC SRM498 Div1 1000PT(容斥原理+DP)
[\(Description\)] 网格中每步可以走\((0,\cdots M_x,0\cdots M_y)\)中任意非零向量,有\(K\)种向量不能走,分别是\((r_1,r_1),(r_2,r_2 ...
随机推荐
- maven 几个命令的用法
进入到项目目 前 cd E:\workspace\foen_api(如切换不了目录) 直接E:\workspace\foen_api mvn clean 清理 mvn install 安装 mvn t ...
- Slide Window 专题
992. Subarrays with K Different Integers 给定一个正整数数组,计算刚好有K个不同数的子数组的个数.(For example, [1,2,3,1,2] has 3 ...
- 牛客提高D4t1 麻将
分析 我们对于每一个点记录他所在的这一行以它为右端点向前最多有几个连续的1 之后我们考虑每一列 对每一列的点按照之前求出的值从小到大排序 一次考虑每一个宽度 而高度也可以很容易的求出 每次取最大值即可 ...
- 凉经-乐糖游戏-PHP开发实习生
收到面试通知当天因为学校出事要求我明天必须回去,所以就买当晚的火车票,然后跟公司说学校有事明天没法去面试了,公司人事比较好给我安排到当天下午面试.公司规模不是很大,但位置好下了地铁到,可能因为招的是实 ...
- 今天刚到货的小米平板2,就出现dnx fastboot mode一直卡死黑屏
http://bbs.xiaomi.cn/t-11786254 今天刚到货的小米平板2,就出现dnx fastboot mode一直卡死黑屏, 发表在晒机评测2015-11-30 14:22:57 来 ...
- 让dcef3支持mp3和h.264 mp4解码播放
嵌入式Chromium框架(简称CEF) 是一个由Marshall Greenblatt在2008建立的开源项目,它主要目的是开发一个基于Google Chromium的Webbrowser控件.CE ...
- 关于 推广QQ
有一个项目 需要在用户提交表单之后,关闭页面,微信公众号发送一个模板消息,链接地址为qq推广的链接. 早上在试 先是在电脑端测试都是正常的. 然后开始上传到服务器端测试,发送模板消息之前的动作,都没有 ...
- 基于K-means Clustering聚类算法对电商商户进行级别划分(含Octave仿真)
在从事电商做频道运营时,每到关键时间节点,大促前,季度末等等,我们要做的一件事情就是品牌池打分,更新所有店铺的等级.例如,所以的商户分入SKA,KA,普通店铺,新店铺这4个级别,对于不同级别的商户,会 ...
- 06:(h5*)Vue第六天
目录 1:iView 2: element 3: vuex 正文 1:i-view 1:装包 npm install view-design --save 2:导包 import ViewUI f ...
- Mac apache You don't have permission to access / on this server.
在mac下配置完apache和php环境后,通过localhost访问页面,出现403Forbidden.页面提示: Forbidden You don't have permission to ac ...