Atcoder 题面传送门 & 洛谷题面传送门

常规题,简单写写罢(((

首先 \(1\) 的位置是什么不重要,我们不妨钦定 \(1\) 号选手最初就处在 \(1\) 号位置,最后答案乘个 \(2^n\) 即可。

显然与 \(1\) 进行比赛的选手一定是区间 \([2,2],[3,4],[5,8],\cdots,[2^{k-1}+1,2^k],\cdots,[2^{n-1}+1,2^n]\) 中的最小值,而由于我们希望 \(1\) 号选手在比赛中取得胜利,故 \([2,2],[3,4],[5,8],\cdots,[2^{k-1}+1,2^k],\cdots,[2^{n-1}+1,2^n]\) 的最小值中不能出现打得过 \(1\) 的选手,于是问题转化为,有多少个 \(2\sim 2^n\) 的排列,使得任意 \(a_i\) 都不是 \([2,2],[3,4],[5,8],\cdots,[2^{k-1}+1,2^k],\cdots,[2^{n-1}+1,2^n]\)。

直接计算不是太容易,考虑容斥,记 \(F(i)\) 为钦定 \(i\) 个 \(a_j\) 是 \([2,2],[3,4],[5,8],\cdots,[2^{k-1}+1,2^k],\cdots,[2^{n-1}+1,2^n]\) 的最小值,剩余随便填的方案数,根据二项式反演,\(ans=\sum\limits_{i=0}^mF(i)(-1)^i\)。

那么怎么求 \(F(i)\) 呢?考虑状压 dp,\(dp_{i,j}\) 表示考虑了 \(a_1\sim a_i\),\(j\) 是一个二进制数,\(j\) 的 \(2^k\) 位为 \(1\) 当且仅当长度为 \(2^k\) 的区间的最小值已经被钦定为 \(a_1\sim a_i\) 中的某个值。考虑转移,显然可以枚举 \(a_{i+1}\) 是否被选择来转移,但是由于你不知道 \((a_i,a_{i+1})\) 中有多少个数已经被填了,故无法计算方案数,因此这个状态设计是不可行的。考虑换个角度,我们反着 \(dp\),\(dp_{i,j}\) 表示考虑了 \(a_{m-i+1}\sim a_m\),这样转移时候,所有被填入 \(j\) 中的区间的数都是 \(\ge a_{m-i+1}\) 的数,转移就容易了许多。枚举 \(a_{m-i}\) 填入了长度为多少的区间,假设为长度为 \(2^k\) 的区间,那么相当于在 \((a_{m-i},2^n]\) 中未填入钦定的区间中的 \(2^n-a_{m-i}-j\) 个数中选择 \(2^k-1\) 个数并排列好,方案数为 \(\dbinom{2^n-a_{m-i}-j}{2^k-1}\times (2^k)!\),预处理组合数转移即可,时间复杂度 \(n^22^n\)。

const int MAXN=16;
const int MAXP=1<<16;
const int MOD=1e9+7;
int n,m,lim,a[MAXN+3],fac[MAXP+5],ifac[MAXP+5];
int dp[MAXN+3][MAXP+5];
void initfac(int n){
fac[0]=ifac[0]=ifac[1]=1;
for(int i=2;i<=n;i++) ifac[i]=1ll*ifac[MOD%i]*(MOD-MOD/i)%MOD;
for(int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%MOD,ifac[i]=1ll*ifac[i-1]*ifac[i]%MOD;
}
int binom(int x,int y){
if(x<y||x<0||y<0) return 0;
return 1ll*fac[x]*ifac[y]%MOD*ifac[x-y]%MOD;
}
int main(){
scanf("%d%d",&n,&m);lim=1<<n;initfac(lim);
for(int i=1;i<=m;i++) scanf("%d",&a[i]);
reverse(a+1,a+m+1);dp[0][0]=1;
for(int i=0;i<m;i++) for(int j=0;j<lim;j++){
for(int k=0;k<n;k++) if(~j>>k&1){
dp[i+1][j|(1<<k)]=(dp[i+1][j|(1<<k)]+1ll*dp[i][j]*binom(lim-a[i+1]-j,(1<<k)-1)%MOD*fac[1<<k])%MOD;
} dp[i+1][j]=(dp[i+1][j]+dp[i][j])%MOD;
}
int ans=0;
for(int i=0;i<lim;i++){
int cnt=__builtin_popcount(i),ways=1ll*dp[m][i]*fac[lim-1-i]%MOD;
if(cnt&1) ans=(ans-ways+MOD)%MOD;else ans=(ans+ways)%MOD;
} printf("%d\n",1ll*ans*lim%MOD);
return 0;
}

Atcoder Regular Contest 093 D - Dark Horse(组合数学+状压 dp)的更多相关文章

  1. AtCoder Regular Contest 093

    AtCoder Regular Contest 093 C - Traveling Plan 题意: 给定n个点,求出删去i号点时,按顺序从起点到一号点走到n号点最后回到起点所走的路程是多少. \(n ...

  2. AtCoder Regular Contest 093 E: Bichrome Spanning Tree(生成树)

    Bichrome Spanning Tree 题意: 给出一个n个点,m条边的无向连通图,现在要给每条边染色,可以染成黑色或者白色. 现在要求在染色完毕后,找出一个至少包含一条黑边和一条白边的最小生成 ...

  3. AtCoder Regular Contest 075 E - Meaningful Mean(树状数组)

    题目大意:求一个数组中,平均值不小于k的连续子序列个数 所有数减去k,算个前缀和出来,就变成二维数点问题了. 没有修改,离线的话就是CZL所说的“NOIP最喜欢的套路”了:倒着加进BIT,以权值为数组 ...

  4. AtCoder Regular Contest 061

    AtCoder Regular Contest 061 C.Many Formulas 题意 给长度不超过\(10\)且由\(0\)到\(9\)数字组成的串S. 可以在两数字间放\(+\)号. 求所有 ...

  5. AtCoder Regular Contest 094 (ARC094) CDE题解

    原文链接http://www.cnblogs.com/zhouzhendong/p/8735114.html $AtCoder\ Regular\ Contest\ 094(ARC094)\ CDE$ ...

  6. AtCoder Regular Contest 092

    AtCoder Regular Contest 092 C - 2D Plane 2N Points 题意: 二维平面上给了\(2N\)个点,其中\(N\)个是\(A\)类点,\(N\)个是\(B\) ...

  7. AtCoder Regular Contest 094

    AtCoder Regular Contest 094 C - Same Integers 题意: 给定\(a,b,c\)三个数,可以进行两个操作:1.把一个数+2:2.把任意两个数+1.求最少需要几 ...

  8. AtCoder Regular Contest 095

    AtCoder Regular Contest 095 C - Many Medians 题意: 给出n个数,求出去掉第i个数之后所有数的中位数,保证n是偶数. \(n\le 200000\) 分析: ...

  9. AtCoder Regular Contest 102

    AtCoder Regular Contest 102 C - Triangular Relationship 题意: 给出n,k求有多少个不大于n的三元组,使其中两两数字的和都是k的倍数,数字可以重 ...

随机推荐

  1. 【UE4 设计模式】享元模式 Flyweight Pattern

    概述 描述 运用共享技术有效地支持大量细粒度对象的复用.系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用. 由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻 ...

  2. STL模板

    目录 栈stack 队列queue 列表List 集合set 映射map 多重映射multimap 对pair 元组tuple 容器containers 算法algorithms 仿函数/函数对象fu ...

  3. 阿里P7面试官:请你简单说一下类加载机制的实现原理?

    面试题:类加载机制的原理 面试官考察点 考察目标: 了解面试者对JVM的理解,属于面试八股文系列. 考察范围: 工作3年以上. 技术背景知识 在回答这个问题之前,我们需要先了解一下什么是类加载机制? ...

  4. Makefile目标文件搜索(VPATH和vpath

    转载:http://c.biancheng.net/view/7051.html 我们都知道一个工程文件中的源文件有很多,并且存放的位置可能不相同(工程中的文件会被放到不同的目录下),所以按照之前的方 ...

  5. 前端面试手写代码——JS数组去重

    目录 1 测试用例 2 JS 数组去重4大类型 2.1 元素比较型 2.1.1 双层 for 循环逐一比较(es5常用) 2.1.2 排序相邻比较 2.2 查找元素位置型 2.2.1 indexOf ...

  6. Gitee图床设置

    https://gitee.com/ 创建新仓库 点击右上角加号->新建仓库,填写基本信息后点击下面的创建即可 https://gitee.com/projects/new 创建新令牌 点击设置 ...

  7. kail入侵win2003 sp2 中文版系统

    攻击机:kail -- IP:192.168.74.132 目标靶机:win2003 sp2 中文版系统-- IP:192.168.74.128 一.扫描漏洞 1. 在kail中运行 namp 192 ...

  8. mininet-2.2.2-170321-ubuntu-14.04.4-server-amd64的使用

    1.使用Vmware打开下载好的mininet-2.2.2-170321-ubuntu-14.04.4-server-amd64 2.登录账号密码都为mininet 3.用命令行生成拓扑,并测试连通性 ...

  9. httprunner3源码解读(3)client.py

    源码目录结构 ApiResponse 这个类没啥好说的 class ApiResponse(Response): """ 继承了requests模块中的Response类 ...

  10. springcloud zuul shiro网关鉴权并向服务传递用户信息

    1.pom文件 <dependencies> <!--eureka客户端--> <dependency> <groupId>org.springfram ...