Atcoder Regular Contest 093 D - Dark Horse(组合数学+状压 dp)
常规题,简单写写罢(((
首先 \(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)的更多相关文章
- AtCoder Regular Contest 093
AtCoder Regular Contest 093 C - Traveling Plan 题意: 给定n个点,求出删去i号点时,按顺序从起点到一号点走到n号点最后回到起点所走的路程是多少. \(n ...
- AtCoder Regular Contest 093 E: Bichrome Spanning Tree(生成树)
Bichrome Spanning Tree 题意: 给出一个n个点,m条边的无向连通图,现在要给每条边染色,可以染成黑色或者白色. 现在要求在染色完毕后,找出一个至少包含一条黑边和一条白边的最小生成 ...
- AtCoder Regular Contest 075 E - Meaningful Mean(树状数组)
题目大意:求一个数组中,平均值不小于k的连续子序列个数 所有数减去k,算个前缀和出来,就变成二维数点问题了. 没有修改,离线的话就是CZL所说的“NOIP最喜欢的套路”了:倒着加进BIT,以权值为数组 ...
- AtCoder Regular Contest 061
AtCoder Regular Contest 061 C.Many Formulas 题意 给长度不超过\(10\)且由\(0\)到\(9\)数字组成的串S. 可以在两数字间放\(+\)号. 求所有 ...
- AtCoder Regular Contest 094 (ARC094) CDE题解
原文链接http://www.cnblogs.com/zhouzhendong/p/8735114.html $AtCoder\ Regular\ Contest\ 094(ARC094)\ CDE$ ...
- AtCoder Regular Contest 092
AtCoder Regular Contest 092 C - 2D Plane 2N Points 题意: 二维平面上给了\(2N\)个点,其中\(N\)个是\(A\)类点,\(N\)个是\(B\) ...
- AtCoder Regular Contest 094
AtCoder Regular Contest 094 C - Same Integers 题意: 给定\(a,b,c\)三个数,可以进行两个操作:1.把一个数+2:2.把任意两个数+1.求最少需要几 ...
- AtCoder Regular Contest 095
AtCoder Regular Contest 095 C - Many Medians 题意: 给出n个数,求出去掉第i个数之后所有数的中位数,保证n是偶数. \(n\le 200000\) 分析: ...
- AtCoder Regular Contest 102
AtCoder Regular Contest 102 C - Triangular Relationship 题意: 给出n,k求有多少个不大于n的三元组,使其中两两数字的和都是k的倍数,数字可以重 ...
随机推荐
- 《python编程:从入门到实践》课后习题及答案
转载: <Python编程:从入门到实践>课后习题及答案-码农之家 (xz577.com) <Python编程:从入门到实践>课后习题及答案 - 信德维拉 - 博客园 (cnb ...
- .Net2.0连接PG数据注意事项
.Net2.0连接PG数据注意事项 第一次用.net操作PG[.NET2.0] 一:Npgsql版本问题 1:如果是.net2.0 建议用2.0.11.0[NuGet搜索npgsql第一个的最低版本 ...
- py3.8安装
ubantu python3.8# 命令下载wget https://www.python.org/ftp/python/3.8.1/Python-3.8.1.tar.xz#解压tar -xvJf P ...
- [对对子队]Alpha阶段项目展示博客
Alpha阶段项目展示博客 1 团队成员的简介和个人博客地址 成员 头像 岗位 博客 个人介绍 黄贤昊 PM 17373253 喜欢玩游戏和做游戏,项目经验基本都和游戏相关,擅长摸鱼,偶尔敬业. 刘子 ...
- 2021.9.21考试总结[NOIP模拟58]
T1 lesson5! 开始以为是个无向图,直接不懂,跳去T2了. 之后有看了一眼发现可暴力,于是有了\(80pts\). 发现这个图是有拓扑序的,于是可以用拓扑排序找最长路径.先找原图内在最长路径上 ...
- cadence 技巧
pcb中如何选中完整的一条网络? 1 edit properties 右边 find nets 2 cadence 选中不同的网络高亮 display--->assign color在opt ...
- Java代理:静态代理、JDK动态代理和CGLIB动态代理
代理模式(英语:Proxy Pattern)是程序设计中的一种设计模式.所谓的代理者是指一个类别可以作为其它东西的接口.代理者可以作任何东西的接口:网络连接.存储器中的大对象.文件或其它昂贵或无法复制 ...
- cf13A Numbers(,,)
题意: Little Petya likes numbers a lot. He found that number 123 in base 16 consists of two digits: th ...
- 使用Magisk+riru实现全局改机
前言 提到全局改机,我们想到修改的不是修改Android源码就是利用Xposed改机,前者成本太高,后者只能修改Java层的数据不够彻底.magisk是Android平台上功能强大的工具,利用它可以随 ...
- for循环中创建线程执行问题
先执行以一个简单的示例: static void Main(string[] args) { List<int> taskConsumes = new List<int>() ...