热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

【ARC068F】Solitaire(dp,计数,思维)

首先发现那个双端队列一定长这样:也就是说,这个队列中的数先单调递减,然后再单调递增,最小值为\(1\)。现在考虑从双端队列中取数,那么当我们取到\(1\)这个数时,我们会在原来的双

首先发现那个双端队列一定长这样:

也就是说,这个队列中的数先单调递减,然后再单调递增,最小值为 \(1\)

现在考虑从双端队列中取数,那么当我们取到 \(1\) 这个数时,我们会在原来的双端队列中取到类似这样的两个数列:(分别用红、蓝表示)

那么红、蓝两数列的总长度为 \(k\),剩下的就是绿色的一段,长度为 \(n-k\),我们每次可以从两端任意取,共取 \(n-k-1\) 次,方案数为 \(2^{n-k-1}\)

所以我们只用考虑前 \(k\) 个数的取法,然后乘上 \(2^{n-k-1}\) 就好了。

由图像,我们看一下弹出序列需要满足什么条件:



  1. 首先第 \(k\) 位肯定是 \(1\)。(题目要求)



  2. \(k\) 个数,一定是由一个或两个单调递减的数列混合而成的(这两个数列就是图中的红、蓝两个数列),并且其中的一个单调递减的数列肯定包含 \(1\) 这个点(蓝色数列)。



  3. \(n-k\) 个数,其最大值应小于某一个提到的单调数列的最小值。也就是绿色段的最大值小于红色段的最小值。



那我们不妨设 \(f(i,j)\) 表示已经取了前 \(i\) 个数,他们的最小值为 \(j\) 时的方案数。(满足上面的 \(3\) 个条件)

那么我们设选的这 \(i\) 个数分成的两个单调递减的序列分别为 \(A\)\(B\),其中最小值 \(j\)\(A\) 中,\(B\) 中的最小值为 \(minn\)

设除了我们选的这 \(i\) 个数剩下的 \(n-i\) 个数组成的集合为 \(S\)\(S\) 中最大的数为 \(maxS\)

大概可以用这张图表示:

\(f(i,j)\) 的定义得,\(B\) 序列已经满足了第 \(3\) 个条件,即 \(maxS

我们现在要从 \(S\) 中选一个数,加入 \(A\)\(B\) 里面。

考虑构造:



  1. 假设加入的数 \(x\) 满足 \(x,那么我们就把它加到 \(A\) 的末尾,此时仍满足所有条件。所以 \(f(i,j)\)\(f(i+1,1)\sim f(i+1,j-1)\) 转移。



  2. 假设加入的数 \(x\) 满足 \(x\geq j\),如果加入 \(A\) 中,\(A\) 就不满足单调递减的性质了,所以只能加入 \(B\) 中。

    然后发现只能把 \(S\) 中的最大值 \(maxS\) 加入到 \(B\) 的队尾(而且必须得满足 \(maxS\geq j\),不然会在第一种情况中算重)。

    由于 \(maxS\)\(S\) 中的最大的数,所以当 \(maxS\) 加入 \(B\) 数列成为 \(B\) 数列的最小值后,仍大于 \(S\) 中的所有数,满足条件。

    所以 \(f(i,j)\)\(f(i+1,j)\) 转移。

    至于为什么 \(S\) 中除 \(maxS\) 的某一个数 \(x\) 都不能加入 \(B\) 的队尾:因为加入后,\(B\) 中的最小值就变成了 \(x\),而 \(S\) 中的最大值仍为 \(maxS\)。此时 \(x,不满足条件。



所以通过 \(f(i,j)\) 就可以向 \(f(i+1,1\sim j)\) 转移了。

显然答案就是 \(2^{n-k-1}\times\sum\limits_{i=2}^{n-k+2}f(k-1,i)\)

还是有很多细节的,详见代码:

#include
#define N 2010
#define ll long long
#define mod 1000000007
using namespace std;
int n,k;
ll f[N][N];
ll poww(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=2;i<=n;i++) f[1][i]=1;
for(int i=1;i {
f[i+1][n-i+1]=f[i][n-i+1];
for(int j=n-i;j>=2;j--)
f[i+1][j]=(f[i+1][j+1]+f[i][j])%mod;
}
ll ans=0;
for(int i=2;i<=n-k+2;i++)
ans=(ans+f[k-1][i])%mod;
if(k==1) ans=1;//特判1:k=1
if(n-k-1>=0) printf("%lld\n",ans*poww(2,n-k-1)%mod);
else printf("%lld\n",ans);//特判2:n=k
return 0;
}


推荐阅读
  • Linux设备驱动程序:异步时间操作与调度机制
    本文介绍了Linux内核中的几种异步延迟操作方法,包括内核定时器、tasklet机制和工作队列。这些机制允许在未来的某个时间点执行任务,而无需阻塞当前线程,从而提高系统的响应性和效率。 ... [详细]
  • 本文提供了使用Java实现Bellman-Ford算法解决POJ 3259问题的代码示例,详细解释了如何通过该算法检测负权环来判断时间旅行的可能性。 ... [详细]
  • FinOps 与 Serverless 的结合:破解云成本难题
    本文探讨了如何通过 FinOps 实践优化 Serverless 应用的成本管理,提出了首个 Serverless 函数总成本估计模型,并分享了多种有效的成本优化策略。 ... [详细]
  • 本文详细探讨了HTML表单中GET和POST请求的区别,包括它们的工作原理、数据传输方式、安全性及适用场景。同时,通过实例展示了如何在Servlet中处理这两种请求。 ... [详细]
  • 深入解析Redis内存对象模型
    本文详细介绍了Redis内存对象模型的关键知识点,包括内存统计、内存分配、数据存储细节及优化策略。通过实际案例和专业分析,帮助读者全面理解Redis内存管理机制。 ... [详细]
  • 探讨如何通过高效的数据库查询和排序策略,优化基于GPS位置信息的附近用户搜索功能,以应对大规模用户数据场景。 ... [详细]
  • 本文探讨了哪些数据库支持队列式的写入操作(即一个键对应一个队列,数据可以连续入队),并且具备良好的持久化特性。这类需求通常出现在需要高效处理和存储大量有序数据的场景中。 ... [详细]
  • Netflix利用Druid实现高效实时数据分析
    本文探讨了全球领先的在线娱乐公司Netflix如何通过采用Apache Druid,实现了高效的数据采集、处理和实时分析,从而显著提升了用户体验和业务决策的准确性。文章详细介绍了Netflix在系统架构、数据摄取、管理和查询方面的实践,并展示了Druid在大规模数据处理中的卓越性能。 ... [详细]
  • 深入解析for与foreach遍历集合时的性能差异
    本文将详细探讨for循环和foreach(迭代器)在遍历集合时的性能差异,并通过实际代码示例和源码分析,帮助读者理解这两种遍历方式的不同之处。文章内容丰富且专业,旨在为编程爱好者提供有价值的参考。 ... [详细]
  • 全面解析运维监控:白盒与黑盒监控及四大黄金指标
    本文深入探讨了白盒和黑盒监控的概念,以及它们在系统监控中的应用。通过详细分析基础监控和业务监控的不同采集方法,结合四个黄金指标的解读,帮助读者更好地理解和实施有效的监控策略。 ... [详细]
  • 本文详细介绍了Grand Central Dispatch (GCD) 的核心概念和使用方法,探讨了任务队列、同步与异步执行以及常见的死锁问题。通过具体示例和代码片段,帮助开发者更好地理解和应用GCD进行多线程开发。 ... [详细]
  • 并发编程 12—— 任务取消与关闭 之 shutdownNow 的局限性
    Java并发编程实践目录并发编程01——ThreadLocal并发编程02——ConcurrentHashMap并发编程03——阻塞队列和生产者-消费者模式并发编程04——闭锁Co ... [详细]
  • 深入解析RDMA中的队列对(Queue Pair)
    本文将详细探讨RDMA架构中的关键组件——队列对(Queue Pair,简称QP),包括其基本概念、硬件与软件实现、QPC的作用、QPN的分配机制以及用户接口和状态机。通过这些内容,读者可以更全面地理解QP在RDMA通信中的重要性和工作原理。 ... [详细]
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
  • 优化Flask应用的并发处理:解决Mysql连接过多问题
    本文探讨了在Flask应用中通过优化后端架构来应对高并发请求,特别是针对Mysql 'too many connections' 错误的解决方案。我们将介绍如何利用Redis缓存、Gunicorn多进程和Celery异步任务队列来提升系统的性能和稳定性。 ... [详细]
author-avatar
趣校区导购网
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有