比赛:2021-08-09:A

本文讲解了一个关于长度为nnn数列通过n-1次合并运算后可能得到的不同结果种数的题目。通过分析XXX运算,发现其实质是求和除以2的操作。文章详细介绍了区间动态规划的方法,包括初始化、状态转移和代码实现。最后给出了代码片段来展示如何利用dp解决该问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意

定义一个运算操作,求出一个长度为 n n n的数列在经过 n − 1 n-1 n1次合并后能得到几种不同的结果。

题目分析

首先先来观察一下这个 X X X运算: a ( X ) b = ( ( a & b ) + ( a ∣ b ) ) > > 1 a(X)b=((a\&b)+(a|b))>>1 a(X)b=((a&b)+(ab))>>1
实际上,这个 ( ( a & b ) + ( a ∣ b ) ) > > 1 ((a\& b)+(a|b))>>1 ((a&b)+(ab))>>1 的值就是等于 ( a + b ) / 2 (a+b)/2 (a+b)/2的值,因为如果 a a a b b b的某一位不同即分别为 0 0 0 1 1 1,那么 a & b a\&b a&b中这一位为0, a ∣ b a|b ab中这一位为1,相加后大小不变。
考虑区间 D P DP DP
设一个布尔三维数组 f f f,区间 i i i j j j能合成 k k k f i , j , k f_{i,j,k} fi,j,k为真,否则为假。
确定 D P DP DP的起点:
当所有数都为一个单独的区间时,那么这个区间只能合成这单独的一个数,可以在输入时就初始化:

scanf("%d",&n);
for(int i=1;i<=n;++i){
	scanf("%d",a+i);f[i][i][a[i]]=1;
}

然后开始 D P DP DP
D P DP DP一个区间时,枚举一个分界线,然后再枚举这个分界线两边的两个区间所能合成的值。把两边区间的合成出来的两个值再进行合并,就是当前区间能够合成出来的值。
由于 a i ≤ 7 a_i \leq 7 ai7,所以能合成出的最大值也为 7 7 7

C o d e Code Code

#include<iostream>
#include<cstdio>
#define sco 200
using namespace std;
int a[sco],n;
bool f[sco][sco][10];
int X(int a,int b){
	return (a+b)/2;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;++i){
		scanf("%d",a+i);f[i][i][a[i]]=1;
	}
	for(int i=2;i<=n;++i){//枚举区间右端点
		for(int j=i;j>0;--j){//枚举区间左端点
			for(int mid=j;mid<=i;++mid){//枚举区间分界线
				for(int l=0;l<=7;++l){//最大值为7
					if(!f[j][mid][l])continue;//如果不能合成当前值就进行下一次循环
					for(int r=0;r<=7;++r){
						if(!f[mid+1][i][r])continue;//同上
						int t=X(l,r);//合并两边区间的合成值
						f[j][i][t]=true;//设置为真
					}
				}
			}
		}
	}
	for(int i=0;i<=7;++i){
		if(f[1][n][i])printf("%d ",i);//输出1~n的区间
	}//输出
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值