Codeforces Round #772(Div.2) [A~D]
链接:contest link
A.Min or Sum
题目
给定一个长度为 \(n\) 的数组 \(a\) ,可以执行任意次如下操作:
- 任取两个整数 \(i,j\) ,使 \(a_i=x,a_j=y\) ,\(x,y\) 需要满足 \(x\mid y=a_i\mid a_j\)
求执行操作后数组元素和的最小值
分析
设 \(x=a_1\mid a_2\mid\cdots\mid a_n\) ,\(x\) 在执行操作的过程中是不变的
而 \(a_1\mid a_2\mid\cdots\mid a_n\leq a_1+a_2+\cdots+a_n\) ,所以元素和的最小值为 \(x\) ,考虑如何操作才能取到最小值,对于任意 \(i\in[1,n-1]\) 使 \(a_i=0,a_{i+1}=a_{i+1}\mid a_i\) 即可
代码
#include<bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int t;
cin >> t;
while(t--) {
int n, a, res = 0;
cin >> n;
for(int i = 1; i <= n; i++) {
cin >> a;
res = res | a;
}
cout << res << endl;
}
return 0;
}
B.Avoid Local Maximums
题目
给定一个长度为 \(n\) 的数组 \(a\) ,可以执行如下操作:
- 任取一个整数 \(i\) ,使 \(a_i=x\) ,\(x\) 满足 \(1\leq x\leq 10^9\)
求最少的操作数,使数组不存在局部最大值
局部最大值的定义是:如果 \(a_{i-1}<a_i\) 且 \(a_i>a_{i+1}\) 那么 \(a_i\) 就是局部最大值
分析
当我们找到一个局部最大值 \(a_{i-1}\) 时,有 \(a_{i-2}<a_{i-1},a_{i-1}>a_i\) ,那么我们可以修改 \(a_i\) ,当 \(a_{i-1}>a_{i+1}\) 时让 \(a_i=a_{i-1}\) ,这样 \(a_{i+1},a_{i-1}\) 就都不可能成为局部最大值,当 \(a_{i-1}\leq a_{i+1}\) 时让 \(a_i=a_{i+1}\) ,同样,\(a_{i+1},a_{i-1}\) 都不可能成为局部最大值。所以贪心策略是:\(a_{i-1}\) 为局部最大值时使 \(a_i=\max(a_{i-1},a_{i+1})\)
代码
#include<bits/stdc++.h>
using namespace std;
const int MAX_N = 200000 + 5;
int a[MAX_N];
int n;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int t;
cin >> t;
while(t--) {
cin >> n;
for(int i = 1; i <= n; i++)
cin >> a[i];
a[n + 1] = 0;
int cnt = 0;
for(int i = 3; i <= n; i++) {
if(a[i] < a[i - 1] && a[i - 1] > a[i - 2]) {
a[i] = max(a[i - 1], a[i + 1]);
cnt++;
}
}
cout << cnt << endl;
for(int i = 1; i <= n; i++)
cout << a[i] << ' ';
cout << endl;
}
return 0;
}
C.Differential Sorting
题目
给定一个长度为 \(n\) 的数组 \(a\) ,可以执行如下操作:
- 任取三个整数 \(x,y,z(1\leq x<y<z\leq n)\) ,使 \(a_x=a_y-a_z\)
求如何操作能使数组变为非减序列,即 \(\forall i,a_i\leq a_{i+1}\)
不要求操作数最小
分析
考虑序列的最后三个数 \(a_n,a_{n-1},a_{n-2}\) ,由上述规则可知 \(a_{n-1}\) 和 \(a_n\) 无法更改,如果 \(a_{n-1}>a_n\) ,那么无论怎么操作都不可能使序列非减
如果 \(a_{n-1}\leq a_n\)
- 当 \(a_n\geq 0\) 时我们可以遵循一个简单的策略:\(i=n-2,n-3,\cdots 1\) 时依次执行操作 \((x,y,z)=(i,i+1,n)\) ,那么 \(a_i=a_{i+1}-a_n\leq a_{i+1}\)
- 当 \(a_n<0\) 时 \(a_{n-2}\) 只有在 \(a_{n-2}\leq a_{n-1}\) 才可保证序列非减,否则 \(a_{n-2}=a_{n-1}-a_n>a_{n-1}\) ,同理可推 \(a_{n-3},a_{n-4},\cdots a_1\) ,所以只有原序列满足非减时才能进行 \(0\) 次操作,否则无论如何操作都不可能使序列非减
代码
#include<bits/stdc++.h>
using namespace std;
const int MAX_N = 200000 + 5;
long long a[MAX_N];
int n;
struct node {
int x, y, z;
} step[MAX_N];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int t;
cin >> t;
while(t--) {
cin >> n;
for(int i = 1; i <= n; i++)
cin >> a[i];
if(a[n - 1] > a[n]) {
cout << -1 << endl;
} else {
int cnt = 0;
bool fnd = true;
for(int i = n - 2; i >= 1; i--) {
if(a[i] > a[i + 1]) {
if(a[n] >= 0) {
a[i] = a[i + 1] - a[n];
step[++cnt] = {i, i + 1, n};
} else {
fnd = false;
break;
}
}
}
if(fnd) {
cout << cnt << endl;
for(int i = 1; i <= cnt; i++)
cout << step[i].x << ' ' << step[i].y << ' ' << step[i].z << endl;
} else {
cout << -1 << endl;
}
}
}
return 0;
}
D.Infinite Set
题目
给定一个长度为 \(n\) 的数组 \(a\) ,每个元素互不相同,设集合 \(S\) 为包含所有满足以下条件的整数 \(x\) :
- \(x=a_i\)
- \(x=2y+1\) 且 \(y\in S\)
- \(x=4y\) 且 \(y\in S\)
给定 \(p\) ,求 \(S\) 中小于 \(2^p\) 的元素个数
分析
参考官方题解,推理自然简明:tutorial
代码
#include<bits/stdc++.h>
using namespace std;
const int MAX_N = 200000 + 5;
const int MOD = 1e9 + 7;
int n, p, ans = 0;
int a[MAX_N], f[MAX_N], cnt[MAX_N];
set<int> useful;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> p;
for(int i = 1; i <= n; i++)
cin >> a[i];
sort(a + 1, a + n + 1);
for(int i = 1; i <= n; i++) {
int x = a[i];
bool flag = false;
while(x > 0) {
if(useful.count(x)) {
flag = true;
break;
}
if(x % 2)
x /= 2;
else if(x % 4 == 0)
x /= 4;
else
break;
}
if(!flag)
useful.insert(a[i]);
}
for(int x : useful)
cnt[__lg(x)]++;
for(int i = 0; i < p; i++) {
f[i] = cnt[i];
if(i >= 1)
f[i] = (f[i] + f[i - 1]) % MOD;
if(i >= 2)
f[i] = (f[i] + f[i - 2]) % MOD;
ans = (ans + f[i]) % MOD;
}
cout << ans << endl;
return 0;
}