蓝桥杯 2025 C++组 省 B 题解

可分解的正整数

算法:思维

因为可以有负数 所以除了1以外的任何数都可以构造

当这个数为x构造方法为

-(x-1)  -(x-2)  -(x-3) ....-1 0 1...x-3 x-2 x-1 x

除了x,x以前的数都会被负数抵消

#include <bits/stdc++.h>
#define ll long long
ll a[100005];
using namespace std;
int main() {
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	ll n;cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	ll ans=0;
	for(int i=1;i<=n;i++){
		if(a[i]!=1) ans++;
	}
	cout<<ans<<"\n";
	
	return 0;
}

产值调整

算法:思维 打表

当三个数相同时 不管怎么调整 结果不会发生改变,所以当三个数相同时break即可

根据模拟题目要求打表后发现,调整100次后 所有数都会变成相同的,所以break后不会使代码超时

#include <bits/stdc++.h>
#define ll long long
ll a[100005];
using namespace std;
int main() {
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	ll t;cin>>t;
	while(t--){
		ll a,b,c,k;cin>>a>>b>>c>>k;
		for(int i=1;i<=k;i++){
			ll na,nb,nc;
			na=(b+c)/2;
			nb=(a+c)/2;
			nc=(a+b)/2;
			a=na;b=nb;c=nc;
            if(a==b and b==c) break;
            
		}
		cout<<a<<" "<<b<<" "<<c<<" "<<"\n";
	}
	return 0;
}

画展布置

算法:前缀和
观察计算公式 需要用到的数皆为平方 提前处理 将每个数平方后 公式将被简化为 每两个数之间的差的和 贪心的思考 使得一组数相邻两个数之间差的和最小 数组有序为最优 先排序 排序后枚举开始的位置 求当前位置到当前位置+m位置的差的和 使用前缀和预处理每个位置的前缀和查询即可。

#include <bits/stdc++.h>
#define ll long long
ll a[100005],b[100005],c[100005];
using namespace std;
int main() {
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	ll n,m;cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	sort(a+1,a+1+n);
	for(int i=1;i<n;i++){
		b[i]=a[i+1]*a[i+1]-a[i]*a[i];
	}
	for(int i=1;i<n;i++){
		c[i]=c[i-1]+b[i];
	}
	ll ans=1e18;
	for(int i=1;i<=n-m+1;i++){
		ans=min(ans,c[i+m-2]-c[i-1]);
	}
	cout<<ans<<"\n";
	
	return 0;
}

水质检测

算法:模拟

按题目要求模拟即可,唯一需要贪心的点,即为

#.
.#

的情况 从左往右判断时 若要使它们联通 最优的方案为

##
.#
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	string s[2];cin>>s[0]>>s[1];
	ll n=s[0].size();
	s[0]=" "+s[0];s[1]=" "+s[1];
	ll ans=0;
	ll l=0,r=0;
	for(int i=1;i<=n;i++){
		if((s[0][i]=='#' || s[1][i]=='#') && l==0){
			l=i;
		}
		if((s[0][i]=='#' || s[1][i]=='#')){
			r=i;
		}
	}
	ll cnt=-1;
	if(s[0][l]=='.' && s[1][l]=='#') cnt=1;
	if(s[1][l]=='.' && s[0][l]=='#') cnt=0;
	
	for(int i=l+1;i<=r;i++){
		if(s[0][i]=='.' && s[1][i]=='.'){
			ans++;
		}else if(s[0][i]=='#' && s[1][i]=='.'){
			if(cnt==1){
				cnt=-1;
				ans++;
			}else{
				cnt=0;
			}
		}else if(s[0][i]=='.' && s[1][i]=='#'){
			if(cnt==0){
				cnt=-1;
				ans++;
			}else{
				cnt=1;
			}
		}else{
			cnt=-1;
		}
	}
	cout<<ans<<"\n";
	return 0;
}

生产车间

算法:树形DP/树上DP

先考虑这道题 但没考虑出来 开始蹭分

于是输出根的权值获得(洛谷50%)

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll a[1005];
int main() {
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	ll n;
	cin>>n;
	ll ans=0;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		
	}
	for(int i=1;i<n;i++) {
		ll o,p;cin>>o>>p;
	}
	cout<<a[1];
	
	return 0;
}

装修报价

方案1:DFS爆搜(30%分)

算法:DFS

为每两个数字之间遍历它们是否为异或。如果当前位置为异或,则提前计算,并储存它们异或后的数字序列。 然后遍历每个位置是‘+’还是‘-’并计算,加入答案。

#include <bits/stdc++.h>
#define ll long long
ll a[100005];
using namespace std;
const ll MOD = 1e9 + 7;
ll ans=0;ll n;
void dfs2(vector<ll> v){
	if(v.size()==1){
		ans+=v[0];
		ans%=MOD;
		return;
	}
	ll it=v[v.size()-1];
	v.pop_back();
	v[0]+=it;
	dfs2(v);
	v[0]-=it;
	v[0]-=it;
	dfs2(v);
}
void dfs(vector<ll> v,ll x){
	if(x>n) {
		dfs2(v);
		return;
	}
	v.push_back(a[x]);
	dfs(v,x+1);
	v.pop_back();
	
	if(v.size()){
		ll tp=v[v.size()-1];
		v[v.size()-1]^=a[x];
		dfs(v,x+1);
		v[v.size()-1];
	}
}
int main() {
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n;
	vector<ll> d;
		ll now=0;
	for(int i=1;i<=n;i++){
		cin>>a[i];now^=a[i];
	}
	dfs(d,1);
	cout<<ans<<"\n";
	return 0;
}

方案2:数学 规律 打表(100%分)

时间复杂度:O(n)

每个数字后都存在‘+’和‘-’,无论之后的数字间填写什么符号,结果都会被抵消,但从第一个位置异或到第i个位置的答案会保留(1<=i<=n)。

位置1异或到3 (1组)
0⊕2⊕5=7
位置1异或到2 (2组)位置3和它之后的都被抵消
0⊕2  +5=7
0⊕2  −5=−3
位置1 (6组) 位置2和它之后的都被抵消
0  +2⊕5=7
0  −2⊕5=−7

0  +2−5=−3
0  −2+5=3

0  +2+5=7
0  −2−5=−7

所以最后的结果为

第一个数字 1组

第一个数字异或到第二个数字 2组

第二个数字异或到第三个数字 6组

第三个数字异或到第四个数字 18组

从第n-1个数字前 每个位置的组数是后一个的三倍 依次递增求和即可

#include <bits/stdc++.h>
#define ll long long
ll a[100005];
using namespace std;
const ll MOD = 1e9 + 7;
ll ans=0;ll n;
int main() {
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n;
	vector<ll> d;
		ll now=0;
	for(int i=1;i<=n;i++){
		cin>>a[i];now^=a[i];
	}
	ll op=2;
	ans+=now;
	now^=a[n];
	ll tp=0;
	for(int i=n-1;i>=1;i--){
		ans+=now*op;
		ans%=MOD;
		now^=a[i];
		op*=3;
		op%=MOD;
	}
	ans%=MOD;
	ans+=MOD;
	ans%=MOD;
	cout<<ans<<"\n";
	return 0;
}
### 第十四届蓝桥杯C++ B 题目解析 以下是关于第十四届蓝桥杯C++ B的部分题目解析及其相关内容: #### 一、整体趋势分析 近年来,蓝桥杯竞赛的难度有所调整,不再单纯依赖“暴力求解”,而是更加注重动态规划 (DP) 和搜索图论的应用。这种变化使得参赛者需要具备更强的算法设计能力和逻辑思维能力[^1]。 #### 二、具体题目解析 由于完整的官方题解可能无法完全公开获取,以下提供部分典型题目的思路和解答方法: ##### 1. 填充问题(Greedy Algorithm) 此题属于典型的贪心类问题。其核心在于如何通过局部最优策略实现全局最优效果。参考某篇博客中的解决方案可知,在处理此类问题时应优先考虑资源分配的最大化利用原则[^2]。 ```cpp #include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; // 输入数据量大小n vector<int> a(n); for(auto &x : a){ cin>>x; } sort(a.begin(),a.end()); long long sum=0LL; for(int i=0;i<n/2;i++)sum +=(long long)(a[n-i-1]-a[i]); cout<<sum<<endl; } ``` 上述代码片段展示了针对该问题的一种高效解决方式——通过对数排序并计算差值来达到目标函数最大化的目的。 ##### 2. 翻转操作(Thinking Problem) 对于涉及字符串或者序列变换的操作,《翻转》这类题目往往考验选手的基础编程技巧与灵活运用能力。通常情况下,可以通过模拟实际过程完成任务;但在某些特殊场景下,则需引入额外的数据结构辅助运算以提升效率。 ```cpp string reverseString(string s, int k){ string res = ""; bool flag=true; while(!s.empty()){ if(flag && k<=s.size()){// 当前段长度大于等于k则反转前k个字符 string temp=s.substr(0,k);reverse(temp.begin(),temp.end());res+=temp;s.erase(0,k); }else{ res+=flag?s:s.substr(s.size()-k+1,s.size());// 不足k个按原样加入结果串 break; } flag=!flag;// 切换状态 } return res+s; } ``` 这里给出了一种基于条件判断逐步构建最终输出的方法,体现了程序设计过程中清晰逻辑的重要性。 #### 总结说明 以上仅列举了两个具有代表性的例子,并附上了相应的实现方案供学习交流之用。更多深入探讨可查阅相关资料进一步了解[^3]。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值