Codeforces Global Round 14 E Phoenix and Computers

news2024/9/22 23:29:44

大意:

一排电脑,每次可以选择打开一台电脑,如果某一台电脑相邻的左边和右边都被打开了,它会自动打开。问打开n台电脑的方案数

思路:

O(n^3)做法

不难发现,在操作过程中,一台台电脑其实就是被分成了几个连通块。特别的,当两个联通块的距离<=1时,它们会合并.

那么不妨首先来考虑一下如何全手动实现一个长为k的连通块的构造。显然,想要全手动连着打开k台电脑,如果我们从第i台开始的话,i后面的若干台被打开的顺序必须是固定的。如果后面有一台是跳着打开的,那么最后一定会有一台电脑被自动开启。先从考虑从第一台电脑开始打开,没什么好说的,方案数就是1,理由如上。如果从第二台电脑开始打开的话,后面几台打开的顺序固定,但是第一台可以在中间任意时间打开而不会影响最终结果,所以方案数应该为k-1。如何计算?可以采用隔板法得到\binom{k-2+1}{1}。同理,从第三台电脑开始的时候,前面两台可以插入后面的任意位置,但是前面两台插入的顺序只有一种方案,所以在后面插入的时候不用考虑插入顺序,所以只需要找到位置即可,所以仍然可以采用隔板法。

最后,我们不难得到连续手动打开长度为k的连通块的方案数为\binom{k-1}{0}+\binom{k-1}{1}+...+\binom{k-1}{k-1}=2^{k-1}

接下来考虑dp.dp[i][j]表示处理到第i位,且前面有j台电脑是手动开的。如果我们再假设最后连续k台都是手动开的,那么显然,第i-k台就是自动开的,那么第i-k-1台就是手动开的了,显然这样就可以实现从dp[i-k-1][j-k]转移到dp[i][j]了,这就是该状态设计的合理性。

具体如何转移?最后面k个手动打开的顺序方案自然就是2^(k-1),但是它们其实也可以插入到前面打开的过程中,所以转移方程为dp[i][j]+=dp[i-k-1][j-1]*C(j,k)*2^(k-1)

最后的总方案数自然就是\sum{dp[n][i]},1<=i<=n

O(n^2)做法

还是从联通块来入手。

我们仔细考虑一下每一次操作造成的影响。当前打开一台电脑,可能导致新产生一个连通块,也可能导致某一个联通块的电脑数量+1,当然也可能会导致两个联通块的合并。

影响的可能性就这么多,而我们最终的目标其实就是构造一个长为n的连通块。

设dp[i][j]表示i台电脑已经打开(这里跟上面设的并不一样,首先i台电脑不一定都在最前面,其次它们不一定都是手动开的)产生j个连通块的话,我们要求的就是dp[n][1]了。

然后思路就有些玄学了

先把我看到的讲一下:


某一个连通块长度增加:

这里有两种情况:

长度+1:也就是在连通块的左/右紧贴着添加,这样有两种选法,加上有j个块,共j*2种选法,这里:dp[i][j]+=dp[i-1][j]*j*2

长度+2:也就是隔一格开电脑,中间自动开。一样有j*2种选法,这里dp[i][j]+=dp[i-2][j]*j*2

新添加一个连通块:

上一步有j-1个连通块,所以总共有j个间隔可以插入,找一个间隔插进去就可以产生一个新的连通块了:dp[i][j]+=dp[i-1][j-1]*j

合并两个连通块:

可以发现,合并两个块也有两种情况。

第一种是两个块中间空了两个格子,随便加上一个另一个也有了。

dp[i][j]+=dp[i-2][j+1]*2*j

第二种是两个块中间空了三个格子,那么放中间就可以了

dp[i][j]+=dp[i-3][j+1]*j


看完上面之后,我其实是存疑的。为什么第一种情况可以认定每一个连通块都有左右两个位置可以放?为什么该情况下插入一格不会导致两个连通块的合并?因为如果两个连通块之间间隔为2的话,放入一个会导致合并,但第一种情况并没有与第三种情况进行去重。以及第二种情况,为什么随便找一个空插进去不会导致连通块合并而一定导致产生新的连通块?

这里给出我自己的解释:我之所以会产生这样的疑问,是因为我默认这n台电脑的位置是固定的,它们就摆在那里了,第一台就是第一台,它左边一定没有别的电脑了。这很合理。但是该方法其实是假设有无数台电脑。注意我们最终的目标是构造一个长为n的连通块,所以只要最终结果一样,两者的情况就是等价的。但是假设电脑有无数台的话,第一台左边就还能插新电脑。这样的好处是简化了问题,所有电脑都是等价的了,我们不用分类讨论。对于另一个疑问,我们假设我们可以自由控制两个连通块之间的距离,当我们需要通过添加一个电脑将它们连接起来时,它们的距离就是1.更加形象的,我们将连通块的连接用绳子来实现。想要一步连接两个连通块,我就将新开的电脑和两个连通块分别用绳子连接起来,就联通了。

上一种是有固定距离的思路,中间插入一个就会导致连通块合并。

下一种中,由于我们用绳子,中间完全可以放好几个。不连起来的话,中间蓝色就是一个独立的连通块,连起来的话,就是一个长为5的连通块。

 这样我们就没有上述疑问了,因为连通块是否连接不再由它们的固定距离来决定,而是由我们的“绳子”来决定,这已经是一种纯粹的“构造”方案了,但是最终结果依然是产生长为n的连通块,所以合理。这是和上一种做法完全不同的思路。

所以你也可能会发现该方法的中间方案数并不对,这也是因为该方法与实际情况的思考角度不同。

code1

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const ll N=410;
//const ll mod=1e9+7;
ll n,mod;
ll ksm(ll x,ll y,ll z)
{
	ll ans=1;
	while(y)
	{
		if(y&1) ans=ans*x%z;
		x=x*x%z;
		y>>=1;
	}
	return ans;
}
ll inv(ll x,ll m)
{
	return ksm(x,m-2,m);
}
ll p[N];
ll pp[N];
void init()
{
	p[0]=1;
	for(int i=1;i<=400;++i) p[i]=p[i-1]*i%mod;
	pp[400]=inv(p[400],mod);
	for(int i=400-1;i>=0;--i) pp[i]=pp[i+1]*(i+1)%mod;
}
ll C(ll n,ll m)
{
	if(n<m) return 0;
	return p[n]*pp[m]%mod*pp[n-m]%mod;
}
ll dp[N][N];
void solve()
{
	
	cin>>n>>mod;
	init();
	for(int i=1;i<=n;++i) dp[i][i]=ksm(2,i-1,mod);
	for(int i=2;i<=n;++i)
	{
		for(int j=2;j<i;++j)
		{
			for(int k=1;k<=j;++k)
			{
				(dp[i][j]+=dp[i-k-1][j-k]*C(j,k)%mod*ksm(2,k-1,mod))%=mod;
			}
		}
	}
	ll ans=0;
	for(int i=1;i<=n;++i) (ans+=dp[n][i])%=mod;
	cout<<ans<<endl;
}
int main()
{
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	//ll t;cin>>t;while(t--)
	solve();
	return 0;
}

code2

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
const ll N=410;
//const ll mod=1e9+7;
ll n,mod;
ll dp[N][N];
void add(ll &a,ll b)
{
	a=(a%mod+b%mod)%mod;
}
ll mul(ll a,ll b)
{
	return a%mod*(b%mod)%mod;
}
void solve()
{
	cin>>n>>mod;
	dp[1][1]=1;
	for(int i=2;i<=n;++i)
	{
		for(int j=1;j<=n;++j)
		{
			add(dp[i][j],mul(dp[i-1][j-1],j));
			add(dp[i][j],mul(dp[i-1][j],mul(j,2)));
			add(dp[i][j],mul(dp[i-2][j],mul(j,2)));
			if(i>2) add(dp[i][j],mul(dp[i-2][j+1],mul(2,j)));
			if(i>3) add(dp[i][j],mul(dp[i-3][j+1],j));
		}
	}
	cout<<dp[n][1]<<endl;
}
int main()
{
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	//ll t;cin>>t;while(t--)
	solve();
	return 0;
}

个人观点,如有错误欢迎指出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/138204.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电磁明渠流量计怎么安装?

1、设备介绍 电磁明渠流量计是由流量显示仪、流速计、液位计组成的流速面积法测流量的明渠测量流量系统。 工作原理&#xff1a;基于法拉第电磁感应定律&#xff0c;当导电流体流过电磁式流速仪的磁场时&#xff0c;在与流速和磁场两者相垂直的方向就会产生与平均流速成正比的…

C++ 数学与算法系列之牛顿、二分迭代法求解非线性方程

1. 前言 前文介绍了如何使用“高斯消元法”求解线性方程组。 本文秉承有始有终的态度&#xff0c;继续介绍“非线性方程”的求解算法。 本文将介绍 2 个非线性方程算法&#xff1a; 牛顿迭代法。二分迭代法。 牛顿迭代法&#xff08;Newtons method&#xff09;又称为牛顿…

千万别熬夜:只有睡觉,才能修复DNA损伤

睡眠是人体的一种修复过程&#xff0c;可以恢复精神和解除疲劳。人的一生中&#xff0c;大约三分之一的时间是在睡眠中度过&#xff0c;良好的睡眠是国际社会公认的三项健康标准之一&#xff0c;而睡眠时间过短或睡眠不佳均会影响健康。在中国&#xff0c;超3亿人存在睡眠障碍、…

基于智能电控柜原理的物联网云平台方案

本方案基于智能电控柜的原理&#xff0c;通过无线传输模块将现场采集到的数据经过无线网络发送到物联网云平台&#xff0c;同时可通过云组态和数据中心将现场画面所见即所得的同步到互联网终端。 用户在安装有监控软件后&#xff0c;可以用手机 APP或者在云平台上直接控制电控柜…

Ubuntu自动登录脚本,expect自动切换用户,xshell自动登录脚本

Ubuntu自动登录脚本&#xff0c;expect自动切换用户&#xff0c;xshell自动登录脚本一、!/usr/bin/expect -f的意义二、spawn命令行&#xff1a;三、send命令&#xff1a;四、expect五、interact命令&#xff1a;六、xshell自动化脚本1、怎么使用脚本2、编写脚本3、vbs的不足本…

https访问流程详解

1. 基础知识 1.1 https起源 鲍勃有两把钥匙&#xff0c;一把是公钥&#xff0c;另一把是私钥。 鲍勃把公钥送给他的朋友们----帕蒂、道格、苏珊----每人一把。 苏珊要给鲍勃写一封保密的信。她写完后用鲍勃的公钥加密&#xff0c;就可以达到保密的效果。 鲍勃收信后&#xf…

jvm-sandbox:基础了解及demo演示

文章目录一、基础准备-被测应用二、代码编写-自定义Module三、jvm-sandbox安装及基础命令四、jvm-sandbox demo演示4.1、改变方法返回4.2、异常注入五、资源链接一、基础准备-被测应用 准备&#xff1a;先创建一个基础的SpringBoot项目并打jar包后在服务器启动 RestControll…

TP5反序列化利用链

说明 该文章来源于同事lu2ker转载至此处&#xff0c;更多文章可参考&#xff1a;https://github.com/lu2ker/ 文章目录说明TP5反序列化利用链下图是Mochazz 大佬画的非常优雅的一张调用链图Action&#xff01;CUT&#xff01;TP5反序列化利用链 本文以第二人称视角重点谈谈给…

max蒙皮动画+动作

首先关于max人物动画&#xff01;如何制作&#xff01; 首先&#xff01; 我们要准备一个模型&#xff01;人物的模型&#xff01; 这是一个人物模型&#xff01;obj的&#xff01;没有任何东西&#xff01;你也可以选择其他&#xff0c;我是从虚幻里面直接导出的&#xff0…

太卷了,华为某领导说招外包只要985!

你听说过华为od吗&#xff1f;od是outsourcing dispatch&#xff08;外包派遣&#xff09;的简称&#xff0c;虽然华为每年会挑选一部分优秀的od员工转为华为正编员工&#xff0c;但od本质上还是外包。最近一位华为员工爆料&#xff1a;太卷了&#xff01;领导说招od员工也要98…

玻纤效应对skew的影响(二)

玻纤效应对对内skew的影响 参数对对内Skew的影响 在一个差分对中&#xff0c;对内skew是由PN走线Dk的差异造成的。导致Dk有差异的原因有很多&#xff0c;例如走线位置&#xff0c;core和pp的玻璃束位置&#xff0c;走线宽度等等。但是这些因素影响角度也不同&#xff0c;下图…

应用程序已被Java 安全阻止-- 如何全局设置Java 控制面板参数

最近遇到一个客户问题&#xff0c;客户方存在一个使用场景为使用IE访问一个页面 之后通过点击页面的按钮调起一个applet程序&#xff0c;结果遇到了一个弹窗告警&#xff1a;应用程序已被Java安全阻止。 对于这个问题 解决方案有两个&#xff1a; 1.将访问的页面站点加入到例外…

BGP在数据中心的应用2——BGP如何适应数据中心网络

注&#xff1a; 本文根据《BGP in the Datacenter》整理&#xff0c;有兴趣和英文阅读能力的朋友可以直接看原文&#xff1a;https://www.oreilly.com/library/view/bgp-in-the/9781491983416/上一部分笔记请参考&#xff1a;https://blog.csdn.net/tushanpeipei/article/deta…

echarts中得一些使用技巧和方法

一、取数据的最大值&#xff1a; let maxNum maxData.sort((a, b) > b - a)[0]&#xff1b; 二、echarts 自适应 所有的echarts里面设置了字体根据最外层body的字体来改变大小 // app.vue中的代码 // 页面开始加载时修改font-size var html document.getElementsByTagN…

VGG详解

入门小菜鸟&#xff0c;希望像做笔记记录自己学的东西&#xff0c;也希望能帮助到同样入门的人&#xff0c;更希望大佬们帮忙纠错啦~侵权立删。 ✨完整代码在我的github上&#xff0c;有需要的朋友可以康康✨ https://github.com/tt-s-t/Deep-Learning.git 目录 一、VGG网络的…

小侃设计模式(二十)-迭代器模式

1.概述 迭代器模式&#xff08;Iterator Pattern&#xff09;提供了一种方法访问一个容器对象中各个元素&#xff0c;而又不暴露该对象的内部细节。迭代器模式用于访问集合中的元素而不需要知道集合底层的数据形式。在JAVA语言中&#xff0c;迭代器模式已经成为其中不可缺少的…

3000字13张图详细介绍RAID0、1、5、6、10、50、60,非常值得收藏!

RAID简述 RAID 是一种用于提高数据存储性能和可靠性的技术&#xff0c;英文全称&#xff1a;Redundant Array of Independent Disks&#xff0c;中文意思&#xff1a;独立磁盘冗余阵列。RAID 系统由两个或多个并行工作的驱动器组成&#xff0c;这些可以是硬盘或者 SSD&#xf…

力扣刷题记录——344.反转字符串、345.反转字符串中的元音、349.两个数组的交集

本专栏主要记录力扣的刷题记录&#xff0c;备战蓝桥杯&#xff0c;供复盘和优化算法使用&#xff0c;也希望给大家带来帮助&#xff0c;博主是算法小白&#xff0c;希望各位大佬不要见笑&#xff0c;今天要分享的是——《344.反转字符串、345.反转字符串中的元音、349.两个数组…

Jvm 系列(十二) JVM的执行引擎全面讲解

JVM 执行引擎 1、执行引擎概述 执行引擎是Java虚拟机核心的组成部分之一。 “虚拟机”是相对于“物理机”的概念&#xff0c;这两种机器都有代码执行能力&#xff0c;其区别是物理机的执行引擎是直接建立在处理机、缓存、指令集和操作系统层面上的&#xff0c;而虚拟机的执行…

国产直流马达驱动芯片SS6216的功能参数以及应用

直流有刷电机驱动芯片SS6216是为消费类产品&#xff0c;玩具和其他低压或者电池供电的运动控制类应用提供了一个集成的有刷电机驱动器解决方案。是为低电压下工作的系统而设计的直流电机驱动集成电路&#xff0c;单通道低导通电阻。具备电机正转/反转/停止/刹车四个功能。 直流…