萌新赛练习

H两难抉择

题目是在两种操作里任选一种执行最多一次,并且操作可以针对数组里的任意元素,即选一种操作,可执行,也可以不执行,若执行,也最多只能执行一次,显而易见的是肯定是在最大元素乘以n和最大元素加n,里面挑选一个最大值进行数组的累加,但最后评测的时候有一个样例没有通过,说明我们考虑的不全面,所以在这里我们需要遍历所有可能的情况,选出最终的最大值

原错误代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin>>n;
    long long a[n];
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
    sort(a,a+n);
    int m=a[n-1]*n;
    int b=a[n-1]+n;
    if(m>b){
        a[n-1]=m;
    }
    else a[n-1]=b;
    long long ans=0;
    for(int i=0;i<n;i++){
        ans+=a[i];
    }
    cout<<ans;
    return 0;
}

正确代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin>>n;
    long long a[n],ans=0;
    for(int i=0;i<n;i++){
        cin>>a[i];
        ans+=a[i];   //不进行操作时的和
    }
    long long mx=ans;
    for(int i=0;i<n;i++){  //枚举每种可能,找出最大值
        mx=max({mx,ans+n,(ans-a[i])+a[i]*n}); //三个数中挑选出最大的数
    }
    cout<<mx;
    return 0;
}

K

本题看起来复杂,定义联通块的大小为其所包含点个数,且最后剩下两个联通块大小的乘积为此图的代价,要最大化此图代价,因此我们肯定是要分成两部分,因此实际上只是求满足a+b=n这个条件对于的a和b的乘积最大值

对于a+b=n计算a,b最大乘积的方式:

n 为偶数时,最优分割是 n/2 * n/2

n 为奇数时,最优分割是 (n-1)/2 * (n+1)/2;

不确定n的奇偶性时,最优分割是 n/2*(n-n/2)

原错误代码

(整形变量类型定义错误,导致中间运算过程数据溢出)

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n,m;//应用long long
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int u,v;
        cin>>u>>v;
    }
    int mx=0;//应用long long
    for(int i=1;i<=n/2;i++){
        mx=max(mx,i*(n-i));
    }
    cout<<mx;
    return 0;
}

正确代码

cpp 复制代码
法一(最优解)。。。。。。
#include<bits/stdc++.h>
using namespace std;
int main(){
    long long n,m;
    cin>>n>>m;
    for(int i=0;i<m;i++){
        long long u,v;
        cin>>u>>v;
    }
    cout<<n/2*(n-n/2);
    return 0;
}


法二(改后代码)运用循环,时间复杂度较高。。。。。。
#include<bits/stdc++.h>
using namespace std;
int main(){
    long long n,m;
    cin>>n>>m;
    for(int i=0;i<m;i++){
        long long u,v;
        cin>>u>>v;
    }
    long long mx=0;
    for(int i=1;i<=n/2;i++){
        mx=max(mx,i*(n-i));
    }
    cout<<mx;
    return 0;
}

I 除法移位

简化题目

1.操作次数可以优化到 n-1 次以下

循环右移的性质决定了:右移 k 次和右移 k % n 次的效果完全相同。

例如,数组长度为 n=5 时:

  • 右移 5 次相当于没移(回到原始状态)
  • 右移 6 次等价于右移 1 次(6 % 5 = 1)

因此,只需考虑 0 ≤ k ≤ n-1 次右移 ,但同时也要注意题目所给条件最多对数组 aa进行 tt次循环右移 操作,因此只需考虑 0 ≤ k ≤min(n-1,t) 次右移,后续的操作会进入循环,无需重复计算。

2. 第 i 次操作后的分子分析

每次右移后,数组的第一个元素(即分子)会发生变化。

右移 i 次后,原数组的第 (n - i) % n + 1 个元素会成为新的分子。

例如:

  • 原数组:[a₁, a₂, a₃, a₄, a₅]
  • 右移 1 次后:新数组为 [a₅, a₁, a₂, a₃, a₄],分子为 a₅(即原数组的第 5 个元素)
  • 右移 2 次后:新数组为 [a₄, a₅, a₁, a₂, a₃],分子为 a₄(即原数组的第 4 个元素)

3. 表达式 S(i) 的转换

原表达式 S = a₁ ÷ a₂ ÷ ... ÷ aₙ 可以改写为:

右移 i 次后,分子变为 a[(n-i) % n +1],分母为剩余元素的乘积。

若所有元素均为正数,则最大化 S 等价于最大化分子,因为分子最大化之后,对应的分母就会减小,S整体变大。

4. 关键结论

0≤i≤min(n-1,t) 的范围内,找到使得 a[(n-i) % n +1] 最大的 i,即为最优解。

正确代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n,t;
    cin>>n>>t;
    long long a[n+1];
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    int cnt=0,mx=0;//cnt是操作次数,mx记录此时最大的分子,即右移后数组第一个元素
   //循环遍历所有可能右移的次数,一定注意从0开始,因为也可以不进行操作,如示例一
    for(int i=0;i<=min(n-1,t);i++){
        if(a[(n-i)%n+1]>mx){
            mx=a[(n-i)%n+1];//更新当前最大值,经过i次右移后,分子,即右移后数组第一个元素变为a[(n-i)%n+1]
            cnt=i;  //更新最优操作次数
        }
    }
    cout<<cnt;
    return 0;
}

F 两难抉择新编

分析题目

与H题类似,只是由数组总和变成了数组异或和,在 C++ 中^是按位异或运算符,因此只需要把H题中的+改为^,于是用sum^=a[i] 来累积计算数组元素的异或和,除此之外, 题目还需要计算修改数组后的最大异或和,可以 利用异或的性质:若原异或和为 sum,修改某个元素 a[i]new_val,则新异或和为:sum ^ a[i] ^ new_val,这是因为:

  • 原数组的异或和包含 a[i]
  • 先异或 a[i] 相当于从总和中移除 a[i](即 sum ^ a[i]
  • 再异或 new_val 相当于加入新值

正确代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin>>n;
    long long a[n+1],sum=0;//数组下标从1开始,则数组a需要开n+1个数组空间
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum^=a[i]; //计算原始数组的异或和
    }
    long long mx=sum;// 把最大异或和初始化为原始数组的异或和,使不进行操作的情况包含在内
    for(int i=1;i<=n;i++){  // 遍历每个可能的数组元素
        for(int j=1;j<=(n/i);j++){ // 对于每个元素a[i],尝试所有可能的x值(1到n/i)
            mx=max({mx,sum^a[i]^(a[i]+j),sum^a[i]^(a[i]*j)});//更新最大的数组异或和
        }
    }
    cout<<mx;
    return 0;
}
相关推荐
??tobenewyorker16 分钟前
力扣打卡第二十一天 中后遍历+中前遍历 构造二叉树
数据结构·c++·算法·leetcode
蓝澈112124 分钟前
迪杰斯特拉算法之解决单源最短路径问题
java·数据结构
呆瑜nuage3 小时前
数据结构——堆
数据结构
蓝澈11213 小时前
弗洛伊德(Floyd)算法-各个顶点之间的最短路径问题
java·数据结构·动态规划
zl_dfq3 小时前
数据结构 之 【堆】(堆的概念及结构、大根堆的实现、向上调整法、向下调整法)(C语言实现)
数据结构
127_127_1273 小时前
2025 FJCPC 复建 VP
数据结构·图论·模拟·ad-hoc·分治·转化
闪电麦坤953 小时前
数据结构:二维数组(2D Arrays)
数据结构·算法
随缘而动,随遇而安13 小时前
第八十八篇 大数据中的递归算法:从俄罗斯套娃到分布式计算的奇妙之旅
大数据·数据结构·算法
水木兰亭16 小时前
数据结构之——树及树的存储
数据结构·c++·学习·算法