蓝桥杯2024年第十五届决赛真题-数位翻转

https://www.dotcpp.com/oj/problem3293.html?sid=16920906&lang=1#editor

小明创造了一个函数f(x)用来翻转x的二进制的数位(无前导 0)。比如f(11)=13,因为11=(1011)2 ,将其左右翻转后,变为13=(1101)2;再比如f(3)=3f(0)=0f(2)=f(4)=f(8)=1等等。

小明随机出了一个长度为 n 的整数数组{a1,a2,...,an},他想知道,在这个数组中选择最多 m 个不相交的区间,将这些区间内的数进行二进制数位翻转(将ai变为f(ai))后,整个数组的和最大是多少?

输入格式
输入共 2 行。
第一行为两个正整数 n, m。
第二行为 n 个由空格分开的整数 a1, a2, ..., an。

输出格式
输出共 1 行,一个整数表示答案。

样例输入
5 3
11 12 13 14 15
样例输出
67
提示
【样例说明 1】只翻转 a1,和为 13 + 12 + 13 + 14 + 15 = 67。

样例输入
6 2
23 8 11 19 16 35
样例输出
134
翻转区间 [a3, a4] 和 [a6],和为 23 + 8 + 13 + 25 + 16 + 49 = 134。

【评测用例规模与约定】
对于 20% 的评测用例,保证 n, m ≤ 20。
对于 100% 的评测用例,保证 n, m ≤ 1000,0ai109

这个题是个动态规划问题,设置 dp 数组dp[i][j][0/1]。其中dp[i][j][0]表示第 i 位不翻转时,恰好前 i 位共有 j 位翻转的最优情况;响应的dp[i][j][1]表示翻转。
状态转移方程就是:

dp[i][j][0]={dp[i1][j][0]+a[i],dp[i1][j][1]+a[i],

dp[i][j][1]={dp[i1][j1][0]+b[i],dp[i1][j][1]+b[i],

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e3+100;
ll a[maxn];
ll b[maxn];
ll tmp[100000];
ll dp[maxn][maxn][2];//1是这个变化,0是不变化 
ll get(ll x){
	
	ll ans=0,p=1,cnt=0;
	while(x){
		tmp[++cnt]=x%2;
		x/=2;
	}
	for(int i=cnt;i>=1;i--){
		ans=ans+p*(tmp[i]);
		p=p*2ll;
	}
	return ans;
}
int main(){
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		b[i]=get(a[i]);
	}
	for(int i=1;i<=n;i++){
		dp[i][0][0]=dp[i-1][0][0]+a[i];
		for(int j=1;j<=m;j++){
			dp[i][j][0]=max(dp[i-1][j][0],dp[i-1][j][1])+a[i];
			dp[i][j][1]=max(dp[i-1][j-1][0]+b[i],dp[i-1][j][1]+b[i]);
		}
	}
	ll ans=0;
	for(int j=0;j<=m;j++){
		ans=max(ans,max(dp[n][j][0],dp[n][j][1]));
	}
	cout<<ans<<endl;
}
posted @   lipu123  阅读(197)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
历史上的今天:
2023-06-08 numpy库
2023-06-08 四.特征工程之特征预处理(无量纲化:归一化、标准化)
2023-06-08 matplotlib画图
2023-06-08 python和TensorFlow中一些常用小知识
2023-06-08 2.3 特征工程之特征提取
2020-06-08 病毒(唯一分解定理+欧拉筛)
点击右上角即可分享
微信分享提示