【做题】arc068_f-Solitaire——糊结论
把所有数字放入双端队列后,结果大概是这样一个排列:
\]
其中\(P_1\)是递减序列,\(P_2\)是递增序列。
我们以\(1\)所在的位置\(k\)分割最终的排列\(A\)。
其中前半部分,形象地讲是由两个递减序列交织在一起组成的。那两个递减序列分别是\(P_1\)的前缀和\(P_2\)的后缀,且至少有一个就是\(P_1\)(\(P_2\))本身。那么,前半部分满足这个性质:
可以划分为两个可为空的递减子序列。
显然这个性质难以直接判定。考虑将其转化。对于其中编号为\(i\)的元素,设\(j\)是\(i\)后面的第一个与\(A_i\)属于不同子序列的元素位置。我们不妨分类讨论一发:
- \(A_i > A_j\),因为两个子序列递减,有\(\forall j \in [i+1,k-1], \, A_i>A_j\)
- \(A_i < A_j\),因为两个子序列递减,有\(\forall j \in [1,i-1], \, A_i<A_j\)
因此,我们得出:
长度为\(n\)的最终排列\(A\)的前半部分可以划分为两个可为空的递减子序列$\implies \(
\) \forall i \in [1,k-1]$,下列条件至少满足一个:
- \(\forall j \in [i+1,k-1], \, A_i>A_j\),记为条件1
- \(\forall j \in [1,i-1], \, A_i<A_j\),记为条件2
我们发现,逆命题也是成立的,因为最长不上升子序列的长度小于等于2。(导弹拦截可经典了)于是我们就获得了一个判断方法。
但还有一个问题,即从\(1\)到\(n\)的排列中任取出两个元素不重复的递减序列\(D_1\),\(D_2\),它们组成的序列\(P\),不一定可以作为\(A\)的前半部分。我们还要保证\(D_1\)的最后一个元素和\(D_2\)的最后一个元素中的较大值大于后半部分的所有元素。依然要对此进行转化。
那么,对于我们已知的一个\(A\)的前半部分,我们尝试将其划分且最大化两个子序列最后一个元素的较大值,设它的位置是\(p\)。显然\(p\)后面没有比\(A_p\)更大的元素,否则能得到更优解。通过简单分类讨论,我们发现所有不满足条件2的元素都大于后半部分的所有元素。因此我们可以直接修改条件2:
\]
故我们得到了前半部分的判断方法。
后半部分的判断就简单多了。它是一个递减序列不断从前面或后面取出元素得到的,即每次取出的元素都是剩下的元素中最大(最小)的。容易得到且证明它合法的充要条件:
$ \forall i \in [k+1,n]$,下列条件至少满足一个:
- \(\forall j \in [i+1,n], \, A_i > A_j\)
- \(\forall j \in [i+1,n], \, A_i < A_j\)
我们终于简化了题意:
求有多少个长度为\(n\)的排列\(A\)满足:
- \(A_k = 1\)
- \(\forall i \in [1,k)\),\(A_i\)小于它前面的所有数或大于它后面的所有数。
- \(\forall i \in (k,n]\),\(A_i\)小于它后面的所有数或大于它后面的所有数。
剩下的就简单了。由递推式可知,后半部分的方案数就是\(2^{n-k-1}\)。而对于前半部分,我们设dp状态\(i,j\)表示当前有\(i\)个元素,最小的满足条件2的元素是其中第\(j\)个(不存在则为\(j+1\)),最终答案就是
\]
时间复杂度\(O(n^2)\)。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2010, MOD = 1e9 + 7;
int dp[2][N],n,k,s,p,sum[N],ans,jc[N],inv[N];
typedef long long ll;
ll power(ll a,int b) {
ll res = 1;
while (b) {
if (b&1) (res *= a) %= MOD;
(a *= a) %= MOD;
b >>= 1;
}
return res;
}
ll comb(int a,int b) {
if (a < 0 || b < 0 || a < b) return 0;
return 1ll * jc[a] * inv[b] % MOD * inv[a-b] % MOD;
}
signed main() {
scanf("%lld%lld",&n,&k);
jc[0] = 1;
for (int i = 1 ; i <= n ; ++ i)
jc[i] = 1ll * jc[i-1] * i % MOD;
inv[n] = power(jc[n],MOD-2);
for (int i = n-1 ; i >= 0 ; -- i)
inv[i] = 1ll * inv[i+1] * (i+1) % MOD;
s = k-1;
p = 0;
sum[2] = 1;
sum[3] = -1;
for (int i = 1 ; i <= s ; ++ i) {
p ^= 1;
memset(dp[p],0,sizeof dp[p]);
for (int j = 1 ; j <= i+1 ; ++ j)
(sum[j] += sum[j-1]) %= MOD;
for (int j = 1 ; j <= i+1 ; ++ j)
(dp[p][j] += sum[j]) %= MOD, sum[j] = 0;
sum[i+2] = 0;
for (int j = 1 ; j <= i+1 ; ++ j) {
(sum[2] += dp[p][j]) %= MOD;
(sum[j+2] -= dp[p][j]) %= MOD;
}
}
for (int i = 1 ; i <= s + 1 ; ++ i) {
(ans += 1ll * comb(n-k+i-1,i-1) * dp[p][i] % MOD);
ans %= MOD;
}
if (k == 1) ans = 1;
if (n > k)
ans = 1ll * power(2,n-k-1) * ans % MOD;
ans = (ans + MOD) % MOD;
printf("%lld\n",ans);
return 0;
}
小结:推导结论实在是一个困难的过程,积极的心态和清晰的思路是不可或缺的。
【做题】arc068_f-Solitaire——糊结论的更多相关文章
- AtCoder Grand Contest 11~17 做题小记
原文链接https://www.cnblogs.com/zhouzhendong/p/AtCoder-Grand-Contest-from-11-to-20.html UPD(2018-11-16): ...
- AtCoder Grand Contest 1~10 做题小记
原文链接https://www.cnblogs.com/zhouzhendong/p/AtCoder-Grand-Contest-from-1-to-10.html 考虑到博客内容较多,编辑不方便的情 ...
- noip做题记录+挑战一句话题解?
因为灵巧实在太弱辽不得不做点noip续下命QQAQQQ 2018 积木大赛/铺设道路 傻逼原题? 然后傻逼的我居然检查了半天是不是有陷阱最后花了差不多一个小时才做掉我做过的原题...真的傻逼了我:( ...
- 从【BZOJ4173】谈做题技巧
题目描述 ----------------------------------------------------------------------------------------------- ...
- PKUWC/SC 做题笔记
去年不知道干了些啥,什么省选/营题都没做. 现在赶应该还来得及(?) 「PKUWC2018」Minimax Done 2019.12.04 9:38:55 线段树合并船新玩法??? \(O(n^2)\ ...
- 退役II次后做题记录
退役II次后做题记录 感觉没啥好更的,咕. atcoder1219 历史研究 回滚莫队. [六省联考2017]组合数问题 我是傻逼 按照组合意义等价于\(nk\)个物品,选的物品\(\mod k\) ...
- BJOI做题记录
BJOI做题记录 终于想起还要做一下历年省选题了2333 然而咕了的还是比做了的多2333 LOJ #2178. 「BJOI2017」机动训练 咕了. LOJ #2179. 「BJOI2017」树的难 ...
- csp退役前的做题计划1(真)
csp退役前的做题计划1(真) 因为我太菜了,所以在第一次月考就会退役,还是记录一下每天做了什么题目吧. 任务计划 [ ] Z算法(Z Algorithm) 9.28 [x] ARC061C たくさん ...
- POI做题笔记
POI2011 Conspiracy (2-SAT) Description \(n\leq 5000\) Solution 发现可拆点然后使用2-SAT做,由于特殊的关系,可以证明每次只能交换两个集 ...
随机推荐
- 在caffe-ssd的环境搭建中遇到报错信息:Makefile:588: recipe for target '.build_release/cuda/src/caffe/layers/softmax_loss_layer.o' failed
错误原因: 1.计算机没有安装GPU 2.有GPU但是NVCCFLAGS设置错误 解决方法: 1.对没有GPU的计算机,需要将Makefile中的CPU之前的#注释去掉,是的caffe运行的处理器进行 ...
- gispro试用版账户注册
1.注册账户 http://www.esri.com/zh-cn/arcgis/products/arcgis-pro/trial 2.分配账户权限 3.gispro可以登录了
- 运行vs时打开一个浏览器窗口,而不是在原有窗口上打开一个标签
1.运行vs时打开一个浏览器窗口,而不是在原有窗口上打开一个标签,结束调试时窗口又关闭了,特别麻烦. 在用swagger调试接口时,好不容易输入了测试数据,然而窗口关闭了,再次调试又得重新输入. 解决 ...
- XML系列之--创建电文格式的XML(一)
关于XML,学校那会,老师在口中仅仅提及,自己也未曾深入接触过,仅是些将最基本XML文件内容显示在web定义的表格中之类的简单操作,如今项目中的收发电文涉及到复杂XML的操作.趁此契机好好回顾下XML ...
- 【Hbase学习之一】Hbase 简介
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 apache-hive-2.1.3 ...
- 【Alpha版本】冲刺阶段——Day3
[Alpha版本]冲刺阶段--Day3 阅读目录 今日进展 问题困难 明日任务 今日贡献量 TODOlist [今日进展] 密码算法方面: 参考了md5/sha1+salt和Bcrypt后,我们决定使 ...
- mysql查询语句 查询方式
- Codeforces 456A - Laptops
题目链接:http://codeforces.com/problemset/problem/456/A One day Dima and Alex had an argument about the ...
- MySql安装和基本管理
一.什么是数据库? mysql就是一个基于socket编写的C/S架构的软件 MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,目前属于 Oracle 旗下公司.MySQL 最流 ...
- Linux下的Jmeter运行测试
本文主要介绍Jmeter脚本如何在Linux通过no GUI的方式运行.总共分三部分: 1.Linux下JDK的安装及环境变量的配置 2.Linux下Jmeter的安装及环境变量的配置 3.运行结果的 ...