Codeforces Round #772 (Div. 2) 解题报告
A. Min Or Sum
题意 :给你一个长度为n的数组,你可以进行多次以下操作
选择两个不同的整数 i 与 j, 用符合 \(a_i | a_j = x | y\) 的 x 和 y 替换他们
问这个数组和的最小值
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <map>
#include <vector>
#include <stack>
#include <set>
#include <sstream>
#include <fstream>
#include <cmath>
#include <iomanip>
#include <unordered_map>
#include <unordered_set>
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0);
#define endl '\n'
#define pb push_back
#define all(x) x.begin(),x.end()
#define all1(x) x.begin()+1,x.end()
#define pi 3.14159265358979323846
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N = 200010,M = 200010,INF = 0x3f3f3f3f,mod = 1e9 + 10;
const double INFF = 0x7f7f7f7f7f7f7f7f;
int n,m,k,t;
int main()
{
ios;
cin >> t;
while(t --)
{
cin >> n;
vector<int> a(n + 1);
for(int i = 1;i <= n;i ++) cin >> a[i];
int ans = a[1];
for(int i = 2;i <= n;i ++) ans |= a[i];
cout << ans << endl;
}
return 0;
}
B. Avoid Local Maximums
题意 : 给定一个数组,可以用任意数字替换数组中的数字,问使得数组不存在极大值的最小操作数,并要求输出操作后的数组
分析 : 线性扫一遍,遇到极大值,将其后的元素变大
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <map>
#include <vector>
#include <stack>
#include <set>
#include <sstream>
#include <fstream>
#include <cmath>
#include <iomanip>
#include <unordered_map>
#include <unordered_set>
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0);
#define endl '\n'
#define pb push_back
#define all(x) x.begin(),x.end()
#define all1(x) x.begin()+1,x.end()
#define pi 3.14159265358979323846
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N = 200010,M = 200010,INF = 0x3f3f3f3f,mod = 1e9 + 10;
const double INFF = 0x7f7f7f7f7f7f7f7f;
int n,m,k,t;
int main()
{
ios;
cin >> t;
while(t --)
{
cin >> n;
vector<int> a(n + 2);
for(int i = 1;i <= n;i ++) cin >> a[i];
int ans = 0;
for(int i = 3;i <= n;i ++)
{
if(a[i - 1] > a[i - 2] && a[i - 1] > a[i])
{
ans ++;
a[i] = max(a[i - 1],a[i + 1]);
}
}
cout << ans << endl;
for(int i = 1;i <= n;i ++) cout << a[i] << ' ';
cout << endl;
}
return 0;
}
C. Differential Sorting
题意 :给定一个数组,定义操作:
任选三个不同的数字 x, y, z, (\(x < y < z\)),使 \(a_x = a_y - a_z\)
问是否能将这个数组构造为非递减的,并将操作输出
分析 : 观察最后两个数,他们是不能被操作的
1.如果\(a_{n - 1} > a_n\) 则不能构造出非递减数组
2.如果\(a_n < 0\) ,\(a_{n - 1} - a_n\) 相当于是增加了,所以,如果存在 i使 \(a_i > a_{i + 1}\) 则无法构造
3.其他情况使\(a_1 ~ a_{n - 2}\) 都为 \(a_{n - 1} - a_n\)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <map>
#include <vector>
#include <stack>
#include <set>
#include <sstream>
#include <fstream>
#include <cmath>
#include <iomanip>
#include <unordered_map>
#include <unordered_set>
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0);
#define endl '\n'
#define pb push_back
#define all(x) x.begin(),x.end()
#define all1(x) x.begin()+1,x.end()
#define pi 3.14159265358979323846
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N = 200010,M = 200010,INF = 0x3f3f3f3f,mod = 1e9 + 10;
const double INFF = 0x7f7f7f7f7f7f7f7f;
int n,m,k,t;
int main()
{
ios;
cin >> t;
while(t --)
{
cin >> n;
vector<int> a(n + 1,-INF);
for(int i = 1;i <= n;i ++) cin >> a[i];
if(a[n - 1] > a[n]) cout << -1 << endl;
else
{
if(a[n] < 0 )
{
bool success = true;
for(int i = 1;i < n;i ++) if(a[i] > a[i + 1]) success = false;
if(success) cout << 0 << endl;
else cout << -1 << endl;
continue;
}
cout << n - 2 << endl;
for(int i = 1;i <= n - 2;i ++) cout << i << ' '<< n - 1 << ' ' << n << endl;
}
}
return 0;
}
D. Infinite Set(好题)
题意 : 给定一个数组,和 数字 p
定义集合 S , S 的元素符合以下条件
1.\(x = a_i (1 <= i <= n)\)
2.\(x = 2 y + 1 (y \in S)\)
3.\(x = 4 y(y \in S)\)
问S中不超过\(2 ^ p\) 的元素个数
\(2 ^ p\) 提示我们考虑二进制,在二进制下上述曹操为
2. x = y << 1 | 1
3. x = y << 2
直白的说,2就是给x的二进制右位补一个1,3就是给x的二进制下右位补两个0
考虑 dp
任何一位上的1 都是由以上两种方式转换过来的
所以 转移方程 : \(f(i) = f(i - 1) + f(i - 2)\)
再考虑每一个数组中的数,如果他可以由数组中的其他数经一系列转换过来,则不考虑他
对于每一个考虑的数,我们将其贡献记为其最高位1所在位数
每一位上的1获得的方案数为 \(f(i)\) , 则 每个数的则集合中的最高位不超 i的数量为\(\sum_1^i f(i)\)
最后加起来就好
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <map>
#include <vector>
#include <stack>
#include <set>
#include <sstream>
#include <fstream>
#include <cmath>
#include <iomanip>
#include <unordered_map>
#include <unordered_set>
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0);
#define endl '\n'
#define pb push_back
#define all(x) x.begin(),x.end()
#define all1(x) x.begin()+1,x.end()
#define pi 3.14159265358979323846
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N = 200010,M = 200010,INF = 0x3f3f3f3f,mod = 1e9 + 7;
const double INFF = 0x7f7f7f7f7f7f7f7f;
int n,m,k;
int main()
{
ios;
cin >> n >> k;
vector<int> a(n + 1),f(N,0);
unordered_map<int,bool> mp;
for(int i = 1;i <= n;i ++) cin >> a[i];
sort(all1(a));
for(int i = 1;i <= n;i ++)
{
int t = a[i];
while(t)
{
if(t == 1) break;
else if(mp[t]) break;
if(t & 1) t >>= 1;
else if(t % 4 == 0) t /= 4;
else break;
}
if(!mp[t])
{
mp[a[i]] = true;
int len = 0;
while((1LL << len) < a[i]) len ++;
if((1LL << len) == a[i]) f[len + 1] ++;
else f[len] ++;
}
}
for(int i = 2;i <= k;i ++) f[i] = (f[i] + f[i - 1] + f[i - 2]) % mod;
LL sum = 0;
for(int i = 1;i <= k;i ++) sum = (sum + f[i]) % mod;
cout << sum << endl;
return 0;
}