[ARC068F] Solitaire [DP]
题面
思路
单调性
首先,显然可以发现这些数在放进双端队列之后肯定是一个$V$形的排布:1在最中间,两边的数都是单调递增
那么我们拿出来的数,显然也可以划分成2个单调递减的子序列(因为我们也是从两边往中间取的)
我们令这两个单调递减的子序列的最小值分别为$p$和$q$,其中$p<q$
那么,有一个结论:任意的的还没有被选取的数$k<q$,证明就是用上面的单调递减理论。
如果有一个数比$q$还要大,那么它肯定会在$p,q$之前被拿出队列,因此不会还没有被选取。
递推
考虑我们新放进一个数$k$
如果$p<k<q$,那么显然这个$k$只能放到$q$的那个单调序列的末尾此时这个单调序列的最小值就是$k$了,但是整个已经拿出来的集合的最小值还是$p$
如果$k<p$,那么$k$可以放到两个单调序列的任意一个的末尾。这两种情况下我们分别会得到$(k,p)$和$(q,k)$这两种最小值组合,此时集合最小值一定为$k$
可以发现,这两种情况中,改变了的都是最小值,而且两种情况之间的不同之处也在于新加入的元素和最小值的大小关系
那么,我们就可以考虑一个以当前取出的数集合大小和最小值为状态的$dp$
设$dp[i][j]$表示当前取出了$i$个数,其中的最小值是$j$
那么由上面的讨论,可以得到状态转移方程:
$dp[i][j]=dp[i-1][j]+\sum_{k>j}dp[i-1][k]=\sum_{k>=j}dp[i-1][k]$
到了K以后的问题
显然,上面方程中的$i$,取值范围是$[1,K)$
第$K$个数要求是放1,那么显然这个1只能放在最小值所在的那个序列末尾
后面剩下的$n-K$个数显然就随便取了,一共有$2^{n-K-1}$种选法(最后一个不用乘2)
那么答案就是$2{n-K-1}\sum_{i=2}{n-K+2} dp[K-1][i]$
Code
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cassert>
#include<cmath>
#define ll long long
#define MOD 1000000007
using namespace std;
inline ll read(){
ll re=0,flag=1;char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
ll dp[2010][2010],p[2010],sum[2010][2010];
int main(){
ll n=read(),k=read();ll i,j;
p[0]=1;
for(i=1;i<=n;i++) p[i]=p[i-1]*2%MOD;
for(i=2;i<=n;i++) dp[1][i]=1,sum[1][i]=n-i+1;
for(i=2;i<k;i++){
for(j=n-i+1;j>=2;j--){
dp[i][j]=(dp[i-1][j]+sum[i-1][j+1])%MOD;
//这里我分开写了,这样清晰一点
}
for(j=n-i+1;j>=2;j--) sum[i][j]=(sum[i][j+1]+dp[i][j])%MOD;
}
ll ans=0;
for(i=2;i<=n-k+2;i++) ans+=dp[k-1][i],ans%=MOD;
if(k==1) ans=1;
if(k==n) printf("%lld\n",ans);
else printf("%lld\n",ans*p[n-k-1]%MOD);
}
[ARC068F] Solitaire [DP]的更多相关文章
- LOJ #2731 [JOI2016春季合宿]Solitaire (DP、组合计数)
题目链接 https://loj.ac/problem/2731 题解 首先一个很自然的思路是,设\(dp[i][j]\)表示选了前\(i\)列,第\(2\)行第\(i\)列的格子是第\(j\)个被填 ...
- AtCoder刷题记录
构造题都是神仙题 /kk ARC066C Addition and Subtraction Hard 首先要发现两个性质: 加号右边不会有括号:显然,有括号也可以被删去,答案不变. \(op_i\)和 ...
- Codeforces Round #130 (Div. 2)
A. Dubstep 字符串模拟. string.find()用法 string str; size_t pos = str.find("WUB"); // 返回匹配的第一个位置 ...
- csp退役前的做题计划1(真)
csp退役前的做题计划1(真) 因为我太菜了,所以在第一次月考就会退役,还是记录一下每天做了什么题目吧. 任务计划 [ ] Z算法(Z Algorithm) 9.28 [x] ARC061C たくさん ...
- UVa 10651 Pebble Solitaire(DP 记忆化搜索)
Pebble Solitaire Pebble solitaire is an interesting game. This is a game where you are given a board ...
- UVA 10651 Pebble Solitaire 状态压缩dp
一开始还在纠结怎么表示一个状态,毕竟是一个串.后来搜了一下题解发现了这里用一个整数的前12位表示转态就好了 ,1~o,0~'-',每个状态用一个数来表示,然后dp写起来就比较方便了. 代码: #inc ...
- 【ARC068F】Solitaire
Description 你有一个双端队列和 \(N\) 个数字,先按 \(1\) 到 \(N\) 的顺序每次从任意一端插入当前数字,再进行 \(N\) 次操作每次可以从两端弹出,求有多少种弹出序列 ...
- uva 10651 - Pebble Solitaire(记忆化搜索)
题目链接:10651 - Pebble Solitaire 题目大意:给出一个12格的棋盘,‘o'代表摆放棋子,’-‘代表没有棋子, 当满足’-oo'时, 最右边的棋子可以跳到最左边的位子,而中间的棋 ...
- UVA - 11427 Expect the Expected (概率dp)
Some mathematical background. This problem asks you to compute the expected value of a random variab ...
随机推荐
- P2661 信息传递 DFS
题目链接:洛谷 P2661 信息传递 一个人要想知道自己的生日,就意味着信息的传递是成环的,因为每轮信息只能传递一个人,传递的轮数就等于环的大小 环的大小就等于环中的两个点到第三个点的距离之和加一,我 ...
- (转)零基础学习 Hadoop 该如何下手?
推荐一些Hadoop家族系列文章,主要介绍Hadoop家族产品,常用的项目包括Hadoop, Hive, Pig, HBase, Sqoop, Mahout, Zookeeper, Avro, Amb ...
- tcl之文件操作-文件名相关
- NOIP PJ游记
Day -1 感觉自信满满,一等奖应该稳了,毕竟初一时我这么菜都拿了二等奖,然后就睡觉了... Day 1 在大巴上玩元气骑士可开心了,车上欢欢喜喜,到了考场,一眼看题,以为很简单. T1硬模拟... ...
- python——“/”运算符和“//”运算符的区别
首先先看单斜杆的用法:举几个例子 >>> print(5/3),type(5/3)1.6666666666666667(None, <class 'float'>) &g ...
- Docker使用入门
docker images 查看本地镜像 docker ps -a 查询容器 docker ps -l 查询最近使用容器 docker rm CONTAINER_ID 删除容器 docker rm ...
- 30-RoutingMiddleware介绍以及MVC引入
1-构建路由 public class Startup { // This method gets called by the runtime. Use this method to add serv ...
- 从Wireshark看TCP连接的建立与关闭
TCP是一种面向连接.可靠的协议.TCP连接的建立与断开,都是需要经过通信双方的协商.用一句话概括就是:三次握手say hello(建立连接):四次握手say goodbye(断开连接).要了解TCP ...
- Android 图片放错位置会拉伸变形
今天做了一个很小的需求,然后需要图片,我给ui要图片.直接给了我三套,还命名 x . xx. 2k 真的一开始都不知道.没有玩过这么正规的.我就用了一张,放到了hdpi下面. 后来同事帮我才知道, 图 ...
- java跨服务器请求url获得数据
在项目中,有时需要通过请求远程服务器上的url获取数据(前提是程序所在服务器可以和url服务器ping成功), 用java在后台发送请求时,用到了java.net.URL, java.net.URLC ...