持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第31天,点击查看活动详情
Codeforces Global Round 21
Problem - A - Codeforces
NIT, the cleaver, is new in town! Thousands of people line up to orz him. To keep his orzers entertained, NIT decided to let them solve the following problem related to orz. Can you solve this problem too?
You are given a 1-indexed array of n integers, a, and an integer z. You can do the following operation any number (possibly zero) of times:
Select a positive integer i such that 1≤i≤n. Then, simutaneously set ai to (aiorz) and set z to (aiandz). In other words, let x and y respectively be the current values of ai and z. Then set ai to (xory) and set z to (xandy). Here or and and denote the bitwise operations OR and AND respectively.
Find the maximum possible value of the maximum value in a after any number (possibly zero) of operations.
Input
Each test contains multiple test cases. The first line contains the number of test cases t (1≤t≤100). Description of the test cases follows.
The first line of each test case contains two integers n and z (1≤n≤2000, 0≤z<230).
The second line of each test case contains n integers a1,a2,…,an (0≤ai<230).
It is guaranteed that the sum of n over all test cases does not exceed 104.
Output
For each test case, print one integer — the answer to the problem.
Example
input
5
2 3
3 4
5 5
0 2 4 6 8
1 9
10
5 7
7 15 30 29 27
3 39548743
10293834 10284344 13635445
output
7
13
11
31
48234367
问题解析
题目是说给你一个数组a和一个数m,说每次可以选一个a[i],把a[i]变成a[i]|m,把m变成a[i] & m,问你最后能得到的数组最大值是多少。
因为a[i]&m操作只会让m变的越来越小,所以最大的那一次就是和数组元素进行运算的第一次。只要拿m都和a[i]进行一次或运算,再从中选最大值即可。
AC代码
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#define endl '\n'
#define int ll
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 2e5 + 50;
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
cin >> t;
while (t--)
{
int n, z, x, res = 0;
cin >> n >> z;
for (int i = 0; i < n; i++)
{
cin >> x;
res = max(res, x | z);
}
cout << res << endl;
}
return 0;
}
Problem - B - Codeforces
For a collection of integers S, define mex(S) as the smallest non-negative integer that does not appear in S.
NIT, the cleaver, decides to destroy the universe. He is not so powerful as Thanos, so he can only destroy the universe by snapping his fingers several times.
The universe can be represented as a 1-indexed array a of length n. When NIT snaps his fingers, he does the following operation on the array:
He selects positive integers l and r such that 1≤l≤r≤n. Let w=mex({al,al+1,…,ar}). Then, for all l≤i≤r, set ai to w. We say the universe is destroyed if and only if for all 1≤i≤n, ai=0 holds.
Find the minimum number of times NIT needs to snap his fingers to destroy the universe. That is, find the minimum number of operations NIT needs to perform to make all elements in the array equal to 0.
Input
Each test contains multiple test cases. The first line contains the number of test cases t (1≤t≤104). Description of the test cases follows.
The first line of each test case contains one integer n (1≤n≤105).
The second line of each test case contains n integers a1, a2, …, an (0≤ai≤109).
It is guaranteed that the sum of n over all test cases does not exceed 2⋅105.
Output
For each test case, print one integer — the answer to the problem.
Example
input
4
4
0 0 0 0
5
0 1 2 3 4
7
0 2 3 0 1 2 0
1
1000000000
output
0
1
2
1
问题解析
题目是说,给你一个数组a,你每次可选一个区间,把这一个区间的值都变成这个区间没有的最小非负数。问要多少次操作才能把他们全变成0.
- 如果数组一开始全是0,就是0次。
- 如果数组只有一段连续的数是非0,就是1次(直接选这段数,这段数没有的最小非负数就是0)
- 其余情况两次就可以搞定(选全部的数,因为有0,所以所有的数都不会变成0,次数我们再全选一次,这次一个0没有 ,全部变成0)
AC代码
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#define endl '\n'
#define int ll
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 2e5 + 50;
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
cin >> t;
while (t--)
{
int n, cnt = 0, flag = 0;
cin >> n;
vector<int>v(n+1);
bool st = true;
for (int i = 0; i <= n; i++)
{
if (i < n)
cin >> v[i];
else v[i] = 0;
if (v[i] == 0)
{
if (!st&&flag==0)
flag = 1;
}
else if (v[i] != 0)
{
if (st)
st = false;
else if (!st && flag == 1)flag = 2;
}
}
cout << flag << endl;
}
return 0;
}
Problem - C - Codeforces
Fishingprince is playing with an array [a1,a2,…,an]. He also has a magic number m.
He can do the following two operations on it:
Select 1≤i≤n such that ai is divisible by m (that is, there exists an integer t such that m⋅t=ai). Replace ai with m copies of aim. The order of the other elements doesn't change. For example, when m=2 and a=[2,3] and i=1, a changes into [1,1,3]. Select 1≤i≤n−m+1 such that ai=ai+1=⋯=ai+m−1. Replace these m elements with a single m⋅ai. The order of the other elements doesn't change. For example, when m=2 and a=[3,2,2,3] and i=2, a changes into [3,4,3]. Note that the array length might change during the process. The value of n above is defined as the current length of the array (might differ from the n in the input).
Fishingprince has another array [b1,b2,…,bk]. Please determine if he can turn a into b using any number (possibly zero) of operations.
Input
Each test contains multiple test cases. The first line contains the number of test cases t (1≤t≤104). Description of the test cases follows.
The first line of each test case contains two integers n and m (1≤n≤5⋅104, 2≤m≤109).
The second line of each test case contains n integers a1,a2,…,an (1≤ai≤109).
The third line of each test case contains one integer k (1≤k≤5⋅104).
The fourth line of each test case contains k integers b1,b2,…,bk (1≤bi≤109).
It is guaranteed that the sum of n+k over all test cases does not exceed 2⋅105.
Output
For each testcase, print Yes if it is possible to turn a into b, and No otherwise. You can print each letter in any case (upper or lower).
Example
input
5
5 2
1 2 2 4 2
4
1 4 4 2
6 2
1 2 2 8 2 2
2
1 16
8 3
3 3 3 3 3 3 3 3
4
6 6 6 6
8 3
3 9 6 3 12 12 36 12
16
9 3 2 2 2 3 4 12 4 12 4 12 4 12 4 4
8 3
3 9 6 3 12 12 36 12
7
12 2 4 3 4 12 56
output
Yes
Yes
No
Yes
No
问题解析
题目是说给你一个数组a和一个数m,每次你可以把一个能被m整除的a[i]给替换成m个a[i]/m,或者把m个连续相同的a[i]合成一个m*a[i],再给你一个数组b,问你能不能根据这两个操作,把a数组变成b数组。
只要把两个数组尽可能的用一操作分散就可以,再看两边数组一不一样。要注意的是最好把分散的数都找另一种方法存起来,不然当a[i]为1e9,m为2的时候,数组是装不下的。
AC代码
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#define endl '\n'
#define int ll
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PII;
const int N = 2e5 + 50;
signed main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
cin >> t;
while (t--)
{
int n, m, n2;
cin >> n >> m;
vector<int>a(n);
vector<PII>x, y;
for (int i = 0; i < n; i++)
{
cin >> a[i];
if (a[i] % m == 0)
{
int cnt = 1;
while (a[i] % m == 0)
{
cnt *= m;
a[i] /= m;
}
if (x.empty() || (!x.empty() && x.back().first != a[i]))
x.push_back({ a[i],cnt });
else if (x.back().first == a[i])
x.back().second += cnt;
}
else
{
if (x.empty() || (!x.empty() && x.back().first != a[i]))
x.push_back({ a[i],1 });
else if (x.back().first == a[i])
x.back().second++;
}
}
cin >> n2;
vector<int>b(n2);
for (int i = 0; i < n2; i++)
{
cin >> b[i];
if (b[i] % m == 0)
{
int cnt = 1;
while (b[i] % m == 0)
{
cnt *= m;
b[i] /= m;
}
if (y.empty() || (!y.empty() && y.back().first != b[i]))
y.push_back({ b[i],cnt });
else if (y.back().first == b[i])
y.back().second += cnt;
}
else
{
if (y.empty() || (!y.empty() && y.back().first != b[i]))
y.push_back({ b[i],1 });
else if (y.back().first == b[i])
y.back().second++;
}
}
if (x.size() != y.size())cout << "No" << endl;
else
{
bool flag = true;
int len = x.size();
for (int i = 0; i < len; i++)
{
if (x[i].first != y[i].first || x[i].second != y[i].second)
{
flag = false;
break;
}
}
if (flag)cout << "Yes" << endl;
else cout << "No" << endl;
}
}
return 0;
}