Acwing第50场周赛题解

Acwing第50场周赛

补题地址:

竞赛 - AcWing

A、数组操作

题目大意:

给定一个长度为 n 的整数数组。

数组中只包含 1 和 −1。

你需要对该数组进行如下操作:

  1. 计算该数组中所有元素的和 s。
  2. 计算该数组的最小前缀和 x。
  3. 输出 s−x 的值。
思路分析:

​ 遍历一下整个数组,然后分别求出所有元素s和以及最小前缀和x,然后输出s - x 即可.

代码:
#include <iostream>
#include <algorithm>
using namespace std;
int n, s = 0, x = 0, tmp;
int main(){
    cin >> n;
    for(int i = 1; i <= n; i ++){
        cin >> tmp;
        s += tmp;
        x = min(x, s);
    }
    cout << s - x << '\n';
    return 0;
}

B、减法操作

题目大意:

给定一个整数 n,执行如下算法:

  1. 如果 n=0,则结束算法。
  2. 找到 n 的最小质因子 d。
  3. 令 n 减去 d 并跳转步骤 1。

请你计算,在算法执行的过程中,一共进行了多少次减法操作。

思路分析:

规律:

  1. n为偶数:
    次数等于n / 2
  2. n为奇数:
    次数等于(n - n的最小质因子) / 2
代码:
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
ll n;
//找x的最小质因子(试除法)
ll fun(ll x){
    for(int i = 2; i <= x / i; i ++){
        if(x % i == 0)return i;
    }
    return x;   //说明x本身就是一个质因子(即不存在最小质因子)
}
int main(){
    cin >> n;
    if(n % 2 == 0)cout << n / 2 << '\n';
    else cout << (n - fun(n)) / 2 + 1 << '\n';
    return 0;
}
/*
1) n为偶数:
次数等于n / 2
2) n为奇数:
次数等于(n - n的最小质因子) / 2
*/

C、环形连通分量

题目大意:

请添加图片描述

思路分析1:

先通过并查集找出所有的连通块,如果一个连通块是环,那么该连通块内的每个结点的度肯定为2.

代码1:
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 2e5 + 5;
int d[N], p[N], st[N];
int n, m;
//并查集查找x的祖宗结点
int find(int x){
    if(x != p[x])p[x] = find(p[x]);
    return p[x];
}
//合并两个集合a和b
void merge(int a, int b){
    if(find(a) != find(b)){
        p[find(b)] = find(a);
    }
}

int main(){
    cin >> n >> m;
    //init:
    for(int i = 1; i <= n; i ++){
        d[i] = 0;
        p[i] = i;
    }
    
    for(int i = 1;i <= m; i ++){
        int a, b;
        cin >> a >> b;
        merge(a, b);
        d[a] ++;
        d[b] ++;
    }
    
    int res = 0;
    //先找出所有的连通块
    for(int i = 1; i <= n; i ++){
        if(p[i] == i){
            res ++;
            st[i] = 1;
        }
    }
    
    //判断连通块是否满足环的条件即连通块中每个结点的度数为2
    for(int i = 1; i <= n; i ++){
        if(st[find(i)] && d[i] != 2){
            st[find(i)] = 0;
            res --;
        }
    }
    
    cout << res << '\n';
    
    return 0;
}
思路分析2

通过dfs直接去搜索连通块,然后判断其中的点是否满足环的条件,即连通块中的每个节点的度数为2.

代码:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 2e5 + 5;
vector<int>h[N];
int d[N], vis[N];
int n, m, f, res = 0;
void dfs(int u){
    vis[u] = 1;
    if(d[u] != 2)f = 0;
    for(int i = 0; i < h[u].size(); i ++){
        int j = h[u][i];
        if(!vis[j])dfs(j);
    }
}

int main(){
    cin >> n >> m;
    for(int i = 1; i <= m; i ++){
        int a, b;
        cin >> a >> b;
        h[a].push_back(b);
        h[b].push_back(a);
        d[a] ++; d[b] ++;
    }

    for(int i = 1; i <= n; i ++){
        if(!vis[i]){
            f = 1;
            dfs(i);
            if(f)res ++;
        }
    }

    cout << res << '\n';
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值