2025牛客寒假算法基础集训营1 (E)

[!note] 比赛链接 https://ac.nowcoder.com/acm/contest/953231

A.茕茕孑立之影

题目标签

构造 数论

题目大意

找到一个数x,x和长度为n的数组中的数互不为倍数,找不到输出-1,否则输出这个数.

解题思路

  • 数组中出现1,则输出-1,任何数都是1的倍数
  • 其他情况下输出范围内的最大数即可 (1e9+7
#include <bits/stdc++.h>
using namespace std;

void solve(){
    int n;cin >> n;
    int arr[n];
        for(int i=0;i<n;i++){
            cin >> arr[i];
        }

        for(auto x : arr){
            if(x == 1) {
                cout << -1 << endl;
                return;
            }
        }
    
        int ans = 1e9 + 7;
        cout << ans << endl ;
}

int main(){
    int t;cin >>t;
    while(t--){
        solve();
    }

    return 0;
}

B. 一气贯通之刃

题目标签

图论

题目大意

在树上寻求简单路径问题,路径不重复不遗漏所有节点,不存在这个路径输出-1

解题思路

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;
    vector<int> d(n+1);
    for (int i =0; i<n-1;i++) ~{
        int u,v;
        cin>>u>>v;
        d[u]++;
        d[v]++;
    }
    
    bool b = true;
    vector<int> l;
    for (int i=1;i<=n;i++) {
        if (d[i] > 2) b = false;
        if (d[i] == 1) l.push_back(i);
    }
    
    if (b && l.size() == 2)
        cout << l[0] << ' ' << l[1] << endl;
    else
        cout << -1 << endl;
    
    return 0;
}

虽然AB解出来了,但是写都写了就不舍得删掉了 留着把


E. 双生双宿之错

题目描述

小红定义一个数组是“双生数组”,当且仅当该数组大小为偶数,数组的元素种类恰好为2种,且这两种元素的出现次数相同。例如 \(\{1, 1, 4, 4, 1\}\) 是双生数组。

现在小红拿到了一个长度为偶数的数组,她可以进行若干次操作,每次操作将选择一个元素,使其加1或者减1。小红希望你计算将该数组变成双生数组的最小操作次数。

输入描述:

每个测试文件均包含多组测试数据。第一行输入一个整数 \(T (1 \leq T \leq 10^4)\) 代表数据组数,每组测试数据描述如下:

  • 第一行输入一个正偶数 \(n (2 \leq n \leq 10^5)\) 代表数组元素数量。
  • 第二行输入 \(n\) 个正整数 \(a_1, a_2, \ldots, a_n (1 \leq a_i \leq 10^9)\) 代表数组元素。

除此之外,保证单个测试文件的 \(n\) 之和不超过 \(10^5\)

输出描述:

对于每组测试数据,新起一行。输出一个整数,代表将该数组变成双生数组的最小操作次数。

测试用例

示例1
  • 输入
3
4
1 1 3 1
4
6 6 6 6
6
1 1 4 4 1 4
  • 输出
2
2
0

解题思路

现将数组排序,分成前后两端,分别找出中位数,然后计算出操作次数,若前后中位数相同,前段-1 或后段+1 取最优解。

AC代码

#include <bits/stdc++.h>
using ll = long long;
using namespace std;
#define all(a) a.begin(), a.end()
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)


void solve(){
    int n;
    cin >> n; 

    vector<int> a(n);
    for(auto &x : a) cin >> x;
    sort(all(a));

    int h = n / 2;
    int ml = a[h /2],mr = a[h + h/2];

    ll ans = LLONG_MAX;
    for(auto xl : {ml,ml - 1}){
        for(auto xr : {mr,mr + 1}){
            if(xl == xr){
                continue;
            }

            ll res = 0;
            for (int i = 0; i < h; i++){
                res += abs(a[i] - xl);
                res += abs(a[h + i] - xr);
            }
            ans = min(ans,res);
        }
    }

    cout << ans << endl;

}
signed main(){
    ios;
    int _ = 1;
    cin >> _;
    while (_--) solve();

    return 0;
}

M. 数值膨胀之美

题目描述

定义一个数组的极差为:数组的元素最大值减去最小值。

小红拿到了一个数组,她准备进行恰好一次操作:选择一个非空区间,将其中所有元素都乘以 2。
小红希望最小化数组的极差,你能帮帮她吗?

输入描述

第一行输入一个正整数 $( n \ (1 \leq n \leq 10^5) ) $代表数组中的元素数量。
第二行输入 $ n $个正整数 $( a_1, a_2, \ldots, a_n \ (1 \leq a_i \leq 10^9) ) $代表数组元素。

输出描述

输出一个整数,代表操作恰好一次后,数组的最小极差。

解题思路

优先将最小值翻倍,扩大区间时应从最小值往次小值从小到大扩展

赛时代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'

int _=1;

void solve(){
    int n;cin >> n;
    vector<int > a(n);
    for(int i=0;i<n;i++){
        cin >> a[i];
    } 

    sort(a.begin(),a.end());
    int t_max,t_min;
    t_max = a[n-1];
    t_min = a[0];
    
    if(t_max == t_min) {
        cout << 0 << endl;
        return;
    }

    int n_max=a[n-2];
    int n_min=a[1];

    int diff1 = abs (max(t_max,t_min*2) - min(t_min*2,n_min));
    int diff2 = abs (max(t_max*2,n_max) - min(t_min*2,n_min));
    
    cout << abs(min(diff1,diff2));
    
}

signed main(){
    //cin >> _;
    while(_--){
        solve();
    }

    return 0;
}

~~赛时使用差分进行计算,由于数据弱了,蒟蒻骗到AC,赛后增强hack数据,该方法已经失效、

AC代码

~~没有,蒟蒻就会这么多了 >v< 也有可能是前世的记忆还未恢复,后面的区域,以后再来探索把 )

End...

posted @ 2025-01-26 21:07  Hmi1234  阅读(84)  评论(0)    收藏  举报