Codeforces Global Round 14 E. Phoenix and Computers(dp)

题意:

n n n台电脑,手动打开电脑 i − 1 i-1 i1 i + 1 i+1 i+1 ,那么电脑 i i i 就会被自动打开。求有多少种手动打开电脑的方案,使得最后全部电脑都被打开,打开电脑顺序不同视为不同的方案。

题解:

显然,第一台电脑和最后一台电脑必定是要手动打开的。

d p [ i ] [ j ] dp[i][j] dp[i][j]为前 i i i 台电脑打开 j j j 台且第 i i i台被打开的方案数。

设最后有 k ( ≥ 1 ) k(\geq 1) k(1)台连续的电脑被打开,对 k k k台电脑的先后顺序进行讨论:

先打开第1个,那么后面只能按顺序来,方案数为 1 1 1

先打开第2个,后面只能按顺序来,前面可以任意插入,方案数为 C ( k − 1 , 1 ) C(k-1,1) C(k1,1)

先打开第3个,前面按顺序来,后面也按顺序来,前后可以互相插入,方案数为 C ( k − 1 , 2 ) C(k-1,2) C(k1,2)

以此类推,总方案数为 C ( k − 1 , 0 ) + C ( k − 1 , 1 ) + C ( k − 1 , 2 ) + . . . . + C ( k − 1 , k − 1 ) = 2 k − 1 C(k-1,0)+C(k-1,1)+C(k-1,2)+....+C(k-1,k-1)=2^{k-1} C(k1,0)+C(k1,1)+C(k1,2)+....+C(k1,k1)=2k1

因为最后有连续 k k k个,那么前 i − k i-k ik 就要打开 j − k j-k jk 个,又因为最后只有 k k k个连续,那么第 i − k i-k ik必定是未打开的,且 i − k − 1 i-k-1 ik1一定是打开的,那么方案数为 d p [ i − k − 1 ] [ j − k ] dp[i-k-1][j-k] dp[ik1][jk] ,这一部分和最后的部分是独立的,最后要结合在一起,就是插空,方案数为 C ( j , k ) C(j,k) C(j,k) ,那么就可以推出状态转移方程了: d p [ i ] [ j ] = ∑ d p [ i − k − 1 ] [ j − k ] ⋅ C ( j , k ) ⋅ 2 k − 1 dp[i][j]=\sum dp[i-k-1][j-k] \cdot C(j,k) \cdot 2^{k-1} dp[i][j]=dp[ik1][jk]C(j,k)2k1

最后要注意一些边界初始化。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int MAXN=4e2+5;
const int inf=0x3f3f3f3f;
ll dp[MAXN][MAXN];
ll c[MAXN][MAXN];
ll qpow(ll a,ll b,ll m)
{
	ll res=1;
	while(b)
	{
		if(b&1) res=res*a%m;
		a=a*a%m;
		b>>=1;
	}
	return res;
}
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
    	c[i][0]=1;
    	c[i][1]=i;
    }
    for(int i=2;i<=n;i++)
    {
    	for(int j=2;j<=i;j++)
    	{
    		c[i][j]=(c[i-1][j-1]+c[i-1][j])%m;
    	}
    }
    dp[1][1]=1;
    dp[2][2]=2;
    for(int i=3;i<=n;i++)
    {
    	dp[i][i]=qpow(2,i-1,m);
    }
    for(int i=3;i<=n;i++)
    {
    	for(int j=1;j<i;j++)
    	{
    		for(int k=1;k<j;k++)
    		{
    			dp[i][j]=(dp[i][j]+dp[i-k-1][j-k]*c[j][k]%m*qpow(2,k-1,m)%m)%m;
    		}
    	}
    }
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
    	//cout<<i<<" "<<dp[n][i]<<endl;
    	ans=(ans+dp[n][i])%m;
    }
    cout<<ans<<endl;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,Codeforces Round 511 (Div. 1)是一个比赛的名称。然而,引用内容中没有提供与这个比赛相关的具体信息或问题。因此,我无法回答关于Codeforces Round 511 (Div. 1)的问题。如果您有关于这个比赛的具体问题,请提供更多的信息,我将尽力回答。 #### 引用[.reference_title] - *1* [Codeforces Round 860 (Div. 2)题解](https://blog.csdn.net/qq_60653991/article/details/129802687)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Codeforces Round 867 (Div. 3)(A题到E题)](https://blog.csdn.net/wdgkd/article/details/130370975)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Codeforces Round 872 (Div. 2)(前三道](https://blog.csdn.net/qq_68286180/article/details/130570952)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值