2022年5月安徽省acm网络预赛(含Accode)

2022年5月安徽省Acm网络预选赛(含Accode)

    • A 加奇减偶
    • B 特殊数组
    • C盒子
    • D卡牌对战
    • E甜品
    • F约数之和
    • G 蔬菜包
    • H区间异或


A 加奇减偶

题目描述
给两个数a、b,可以对a进行如下的操作:a = a + x,x是任意的大于0的奇数, a = a - y, y是任意的大于0的偶数。可以执行任意次数以上的操作。
问从a变成b最少需要几次操作?
输入说明
第一行输入一个整数T,代表测试样例数目。 1 <= T <= 30000
接下来T行每一行输入两个整数a, b。 1 <= a, b <= 1000000000
输出说明
对于每一个样例的答案占一行,输出从a变成b的最小操作次数。
输入样例
5
2 3
10 10
2 4
7 4
9 3
输出样例
1
0
2
2
1
提示
对于第一个样例,你只需要对a 加上1。
对于第二个样例,你不需要任何操作。
对于第三次样例,你可以对a加两次1。
对于第四个样例,你可以先对a加上1,再对a减去4。
对于第五个样例,你可以直接减去6。

AC码:

#include 
using namespace std;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int _; cin >> _;
while (_--) {
int a, b;
cin >> a >> b;
int cnt = 0;
if (a < b) {
cnt = 1;
if (a % 2 == b % 2) ++cnt;
}
else if (a > b) {
cnt = 1;
if (a % 2 != b % 2) ++cnt;
}
cout << cnt << '\n';
}
return 0;
}









B 特殊数组

题目描述
定义数组中的某个数ai如果是特殊的,则满足:在数组中存在一个长度大于等于2的连续子序列,其和为ai。
给你一个长度为n的数组,问有多少数是特殊的。
输入说明
第一行输入一个T,代表测试样例个数, 1 <= T <= 1000
接下来2T行,第一行输入一个整数n,代表数组中元素的个数
第二行输入n个整数ai,代表数组中的元素。
其中,1 <= n <= 8000, 1 <= ai <= 8000
输出说明
对于每个测试样例,输出一个整数代表答案,每个样例答案占一行。
输入样例
5
9
3 1 4 1 5 9 2 6 5
3
1 1 2
5
1 1 1 1 1
8
8 7 6 5 4 3 2 1
1
1
输出样例
5
1
0
4
0
解释/提示
对于第一组数据,4有{3, 1}的子序列,前一个5有{1,4},9有{3,1,4,1},6有{1,5},后一个5有{4,1},所以特殊的数有5个。
第二组数据只有2有{1, 1}的子序列满足要求。
第三组数据没有能满足条件的子序列。
第四组有7,6,5,3满足条件。
第五组没有满足条件的子序列。

AC码:

#include 
using namespace std;
constexpr int maxn = 8000;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int _; cin >> _;
while (_--) {
int n; cin >> n;
vector<int> arr(n);
for (auto &x : arr) cin >> x;
int lim = *max_element(begin(arr), end(arr));
bitset<maxn + 1> st;
for (int i = 0; i < n; ++i) {
int sum = 0;
for (int j = i; j < n; ++j) {
sum += arr[j];
if (sum > lim) break;
if (j - i >= 1) st[sum] = 1;
}
}
int cnt = 0;
for (auto &x : arr) cnt += st[x];
cout << cnt << '\n';
}
return 0;
}








C盒子

题目描述
给一个长方体,可以由两个对角顶点坐标确定,一个顶点位于原点(0,0,  0),另一个顶点在点(x1, y1, z1)处。盒子的六个面编号为a1, a2, …, a6,每个面的正中央印有一个数字x。

编号位于框上,如下所示:
数字a1写在ZOX平面上的面上;
a2写在与a1所在的平面平行的面上;
a3写在XOY平面上的面上;
a4写在与a3所在的平面平行的面上;
a5写在YOZ平面上的面上;
a6写在与a5所在的平面平行的面上;
此时,你在(x, y, z)处看长方体。
请注意,长方体的所有面都不是透明的,你无法通过长方体看到数字且你能看得足够远,求出你能看清所看到的面上数字,求能看到的数字之和。
输入说明
第一行输入三个整数x, y, z ,且 |x| , |y|, |z| <=1000000,表示视点位置;
第二行输入三个整数x1, y1, z1 1<= x1, y1, z1 <= 1000000,表示长方体另一顶点坐标;
第三行按编号a1, a2, a3, a4, a5, a6顺序输入六个整数。
数据保证(x, y, z)在长方体之外。
输出说明
输出一个整数,表示你能看到的所有面上的数字之和。
输入样例 1
2 2 2
1 1 1
1 2 3 4 5 6
输出样例 1
12
输入样例 2
0 0 10
3 2 3
1 2 3 4 5 6
输出样例 2
4

AC码:

#include 
using namespace std;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
vector<int> a(3), b(3);
for (auto &x : a) cin >> x;
for (auto &x : b) cin >> x;
swap(a[0], a[1]); swap(a[1], a[2]);
swap(b[0], b[1]); swap(b[1], b[2]);
vector<int> seq(6);
for (auto &x : seq) cin >> x;
int tot = 0;
for (int i = 0; i < 3; ++i)
if (a[i] < 0)
tot += seq[i * 2];
else if (a[i] > b[i])
tot += seq[i * 2 + 1];
cout << tot << '\n';
return 0;
}







D卡牌对战

题目描述:
有2N张牌,它们的点数分别为1到2N。小柯拿了其中的N张,小鹏拿了剩下的N张. 小柯和小鹏会进行N轮游戏,在每轮游戏中,小柯和小鹏各出一张牌。出了的牌不能收回。每轮谁的牌点数大谁就赢; 已知小鹏每一轮会出什么牌,试求小柯最多能赢多少轮。
输入说明:

第一行是一个整数N,
第二行是这N个整数,表示小鹏每轮的出牌。
2<=N <= 200000,

输出说明:

小柯最多能赢几轮
样例输入
4
1 3 4 8
样例输出
3

解释/提示:
小鹏手里的牌是1 3 4 8
小柯手里的牌为2 5 6 7
显然小柯可以选择用
2 v 1
5 v 3
6 v 4
7 v 8
这样就可以赢3轮

AC码:

#include 
using namespace std;
constexpr int maxn = 2e5;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int n; cin >> n;
vector<int> a(n), b;
for (auto &x : a) cin >> x;
sort(begin(a), end(a));
bitset<maxn + 1> st;
for (auto &x : a) st[x] = 1;
for (int i = 1; i <= n * 2; ++i)
if (!st[i]) b.push_back(i);
int cnt = 0;
while (!a.empty()) {
if (!b.empty() and b.back() > a.back()) {
b.pop_back();
++cnt;
}
a.pop_back();
}
cout << cnt << '\n';
return 0;
}








E甜品

题目描述
小怡开了一家蛋糕店,她有n个顾客,每位顾客i都有一个喜好的甜度值a[i](1<=i<=n)。甜度为k的蛋糕,当且仅当|a[i]-k|<=p 时,顾客i才能得到满足。给定n个顾客喜好的甜度值,小怡想知道最多可以让多少顾客得到满足。
输入说明
第一行两个数n, p(1≤n,p≤1000000),含义如题面描述。
接下来一行n个整数,表示顾客喜好的甜度值a[i] (1≤a[i]≤1000000)。
输出说明
输出一个数字,表示最多有多少顾客同时得到满足。
输入样例
6 2
1 5 3 2 4 6
输出样例
5
说明/提示
甜度调成3或4,都可以满足5名顾客。

AC码:

#include 
using namespace std;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int n, p;
cin >> n >> p;
vector<int> arr(n);
for (auto &x : arr) cin >> x;
sort(begin(arr), end(arr));
int cnt = 0;
for (int i = 0; i < n; ++i) {
int j = upper_bound(arr.begin(), arr.end(), arr[i] + p * 2) - arr.begin();
cnt = max(cnt, j - i);
}
cout << cnt << '\n';
return 0;
}





F约数之和

题目描述
给N(1<=N<=30)个正整数,好奇的小明想知道这N个正整数的乘积,是否可以将其分解为2个正整数a和b的乘积,并且a的约数个数与b的约数个数之差为 1 个
输入说明
第一行为一个整数 n 。 第 2∼n+1 行为给出的n个正整数。 (输入数据保证存在唯一解)
输出说明
输出包含两行。 第一行输出 a 和 a 的约数个数。 第二行输出 b 和 b 的约数个数。 输出保证 a 的约数个数大于 b 的约数个数。
输入样例
2
1
2800
输出样例
175 6
16 5

说明/提示
测试数据在 long long 范围内。

2022年5月安徽省acm网络预赛(含Accode)_第1张图片

AC码:

#include 
using namespace std;
using ll = long long;
vector<pair<ll, ll>> seq;
vector<ll> sa;
ll a, b, da, db;
bool dfs(int idx) {
if (idx == seq.size()) {
ll ca = 1, cb = 1, cda = 1, cdb = 1;
for (int i = 0; i < seq.size(); ++i) {
for (int j = 0; j < sa[i]; ++j)
ca *= seq[i].first;
cda *= (sa[i] + 1);
for (int j = 0; j < seq[i].second - sa[i]; ++j)
cb *= seq[i].first;
cdb *= (seq[i].second - sa[i] + 1);
}
if (cda - cdb == 1) {
a = ca, b = cb, da = cda, db = cdb;
return true;
}
return false;
}
for (int i = 0; i <= seq[idx].second; ++i) {
sa[idx] = i;
if (dfs(idx + 1)) return true;
}
return false;
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int n; cin >> n;
ll val = 1;
for (int i = 0; i < n; ++i) {
ll x; cin >> x;
val *= x;
}
for (ll i = 2; i * i <= val; ++i) {
if (val % i == 0)
seq.push_back({i, 0});
while (val % i == 0) {
++seq.back().second;
val /= i;
}
}
if (val > 1) seq.emplace_back(val, 1);
sa.resize(seq.size());
dfs(0);
cout << a << ' ' << da << '\n';
cout << b << ' ' << db << '\n';
return 0;
}








G 蔬菜包

题目描述
小星是参加防疫的一名志愿者,每天都为在家中被隔离的居民们送蔬菜包。他把每层楼看成一个nn的矩阵。小星需要将蔬菜包送到位于m层的居民手中,小星想请你帮他计算一下,他能否成功将蔬菜送达。如果能则需要的最少体力,如果不能则输出No。
输入说明
第一行输入2个整数m(1<=m<=30)和n(1<=n<=30)。表示给出m层楼,每层楼大小为n
n。
接下来m个输入n*n的矩阵表示第m层楼的地图
每层楼至多2个楼梯,第一层楼给出一个起点,以及至多2个楼梯,最后一层楼给出1个终点,中间每层楼的起点为上一层楼梯的位置,上楼不消耗体力。
小星可以消耗3体力可以在一个方向上行动2格并穿过第一格上的障碍物
可以消耗1体力行动1格或2格,可以只走1格,也可以走2格(可以转弯)
#表示障碍物
. 表示平地
S表示起点
E表示居民的位置
U表示楼梯
输出说明
可以回到点内时输出一个整数表示送到目标居民家中所消耗的最小体力,无法送达则输出No。
输入样例1
3 5
##…
S#.U.
##…

…###
…#S#
…###
…#
U…#


.####
…E
.####
S…
输出样例 1
12
输入样例 2
3 5
##…
S#.U.
##…
U…

…#…
…#S.
…#…
S.#…
…#.U


…E

…##
…#S
输出样例 2
10
输入样例 3
3 5
##…
S#.U.
##…
U…

…#…
…#S.
…#…
S.#…
…#.U


…E
…##
…###
…##S
输出样例 3:
No


样例3说明:因为样例中第三层S往可以通行方向(左侧或上侧)都有两个障碍物,穿过第一个后没有落脚点,所以无法穿过障碍物到达E。

2022年5月安徽省acm网络预赛(含Accode)_第2张图片


AC码:
#include 
using namespace std;
constexpr int inf = 0x3f3f3f3f;
constexpr int szd = 4 * 3;
constexpr int maxn = 30 + 1;
constexpr int dirs[][2] {0, 1, 1, 0, 0, -1, -1, 0,
0, 2, 2, 0, 0, -2, -2, 0, -1, -1, -1, 1, 1, 1, 1, -1};
struct node {
int r, c, w;
node (int r, int c, int w) : r(r), c(c), w(w) {};
bool operator < (const node &x) const {
return w > x.w;
}
};
int m, n;
vector<vector<string>> mat;
int memo[maxn][maxn][maxn];
int bfs(int level, int sr, int sc) {
if (memo[level][sr][sc] != -1) return memo[level][sr][sc];
priority_queue<node> pq;
pq.emplace(sr, sc, 0);
vector<vector<int>> d(n, vector<int>(n, inf));
d[sr][sc] = 0;
int min_cost = inf;
while (!pq.empty()) {
auto [r, c, w] = pq.top(); pq.pop();
if (d[r][c] < w) continue;
if (mat[level][r][c] == 'E') return w;
if (mat[level][r][c] == 'U')
min_cost = min(min_cost, w + bfs(level + 1, r, c));
for (int i = 0; i < szd; ++i) {
int nr = r + dirs[i][0], nc = c + dirs[i][1];
if (nr < 0 or nr >= n or nc < 0 or nc >= n) continue;
if (mat[level][nr][nc] == '#') continue;
if (i == 8) {
if (mat[level][r][c - 1] == '#' and mat[level][r - 1][c] == '#') continue;
}
else if (i == 9) {
if (mat[level][r][c + 1] == '#' and mat[level][r - 1][c] == '#') continue;
}
else if (i == 10) {
if (mat[level][r + 1][c] == '#' and mat[level][r][c + 1] == '#') continue;
}
else if (i == 11) {
if (mat[level][r + 1][c] == '#' and mat[level][r][c - 1] == '#') continue;
}
int curr;
if (i < 4 or i >= 8) curr = 1;
else if (i < 8) {
int tr = r + dirs[i - 4][0], tc = c + dirs[i - 4][1];
if (mat[level][tr][tc] == '#') curr = 3;
else curr = 1;
}
if (d[nr][nc] > d[r][c] + curr) {
d[nr][nc] = d[r][c] + curr;
pq.emplace(nr, nc, d[nr][nc]);
}
}
}
return memo[level][sr][sc] = min_cost;
}
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cin >> m >> n;
mat = vector<vector<string>>(m, vector<string>(n));
for (int i = 0; i < m; ++i)
for (auto &s : mat[i])
cin >> s;
memset(memo, -1, sizeof memo);
auto find = [&]()->pair<int, int> {
for (int r = 0; r < n; ++r)
for (int c = 0; c < n; ++c)
if (mat[0][r][c] == 'S') return {r, c};
return {0, 0};
};
auto [sr, sc] = find();
int cost = bfs(0, sr, sc);
if (cost != inf) cout << cost << '\n';
else cout << "No" << '\n';
return 0;
}








H区间异或

题目描述:
小可在五年级暑假开始学习编程,编程语言中有一种“按位异或(xor)”的运算引 起了他的莫大兴趣。于是,他思考这样的一个问题:给一个长度为 n 的整数序列 A和整数k,如何计算出满足下列两个条件的整数对 (l, r) 的数量。
1、1≤l≤r≤n;
2、Al xor A(l+1) xor … xor Ar =k。
小可可虽然提出了问题,但他自己不会解决,只好又要麻烦你解决啦。
说明:xor 就是按位异或(C 或 C++语言中“按位异或”运算符为^)


输入说明:
输入有三行:
第一行一个正整数 n,表示整数序列 A 的元素个数。
第二行有 n 个整数,第 i 个整数 Ai 表示整数序列 A 的第 i 个元素的值。
第三行是一个正整数k,
对于全部测试样例: 1≤ n ≤ 200000,0≤ Ai ≤ 2^20。
输出说明:
输出一行,包括一个正整数,表示满足条件的整数对 (l, r) 的数量。
输入样例:
4
2 5 3 3
7
输出样例:
2

AC码:

#include 
using namespace std;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int n; cin >> n;
vector<int> arr(n);
for (auto &x : arr) cin >> x;
int k; cin >> k;
for (int i = 1; i < n; ++i)
arr[i] ^= arr[i - 1];
map<int, int> mp;
mp[0] = 1;
int cnt = 0;
for (int i = 0; i < n; ++i) {
cnt += mp[arr[i] ^ k];
++mp[arr[i]];
}
cout << cnt << '\n';
return 0;
}





作为也参加了本次比赛的参赛选手,以上仅用作学习用途,版权归原创者所有。若本次收录的题目无意冒犯了贵司版权,请及时联系我,确认后,我会尽快删除。

你可能感兴趣的:(#,ACM,算法,数据结构,图论,c++)