Acwing第50场周赛
补题地址:
A、数组操作
题目大意:
给定一个长度为 n 的整数数组。
数组中只包含 1 和 −1。
你需要对该数组进行如下操作:
- 计算该数组中所有元素的和 s。
- 计算该数组的最小前缀和 x。
- 输出 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,执行如下算法:
- 如果 n=0,则结束算法。
- 找到 n 的最小质因子 d。
- 令 n 减去 d 并跳转步骤 1。
请你计算,在算法执行的过程中,一共进行了多少次减法操作。
思路分析:
规律:
- n为偶数:
次数等于n / 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;
}