这里写目录标题
A Download More RAM
题解
有n个软件,最初有k个内存,每个软件运行需要ai的内存,运行完可以获得bi个内存,问最后可以获得多少内存?
通过排序先运行所需内存小的软件以获得内存,即排序。
代码
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 111;
struct ab
{
int a, b;
} arr[maxn];
bool cmp(ab a, ab b){
return a.a < b.a;
}
int main(){
int t; cin >> t;
while(t--){
int n, k; cin >> n >> k;
for(int i = 0; i < n; i++) {
cin >> arr[i].a;
}
for(int i = 0; i < n; i++){
cin >> arr[i].b;
}
ll ans = k;
sort(arr, arr + n, cmp);
int pos = 0;
while(arr[pos].a <= ans && pos < n){
ans += arr[pos].b;
pos++;
}
cout << ans << '\n';
}
}
B GCD Arrays
题目
给你
l
l
l到
r
r
r这一段序列,在经过k次操作后,该段序列的最大公因数(即当前序列中的所有数字求解gcd)能否是大于1的数
操作:
从序列中取两个数字,将他们永久的从序列中删除,并加两者的乘积加入到队列中
题解
计算连续数字奇数的个数,即为可操作的最大个数,举例如下
初始状态
3
,
4
,
5
,
6
,
7
3,4,5,6,7
3,4,5,6,7
第一次操作
3
∗
5
,
4
,
6
,
7
3*5,4,6,7
3∗5,4,6,7
第二次操作
3
∗
5
∗
7
,
4
,
6
3*5*7,4,6
3∗5∗7,4,6
可以发现如上两次操作所得序列的gcd都是1
第三次操作
3
∗
5
∗
7
∗
4
,
6
3*5*7*4,6
3∗5∗7∗4,6
第四次操作
3
∗
5
∗
7
∗
4
∗
6
3*5*7*4*6
3∗5∗7∗4∗6
显然从第三次操作起开始序列存在大于1的公因数了
那么解题思路就是所有奇数结合再加一个偶数序列即可得到大于1的公因数了
计算奇偶数的办法
ll odd = (r - l + 1) / 2;
ll even = (r - l + 1) / 2;
if ((r - l + 1) % 2 == 1 && r % 2 == 1) odd ++;
else even ++;
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
//freopen("in.txt","r",stdin);
int t; cin >> t;
while(t--){
ll l, r, k;
cin >> l >> r >> k;
if (l == r)
{
if (l == 1)
printf("NO\n");
else
printf("YES\n");
continue;
}
ll odd = (r - l + 1) / 2;
ll even = (r - l + 1) / 2;
if ((r - l + 1) % 2 == 1 && r % 2 == 1) odd ++;
else even ++;
//3个奇数可以操作三次
//printf("%lld\n", odd);
if (odd <= k){
printf("YES\n");
}
else{
printf("NO\n");
}
}
}
C Meximum Array
Mex (mathematics)
补集的最小值
题意
给你n个非负数字,你可以进行如下操作,每次选择连续的k个数字,求解这k个数字的Mex,然后放到b序列中,问最长长度为m的字典序的b序列里面的元素是什么?求解数字m和m个元素。
题解
题目要求是要字典序最大的,那么第一个位置一定是整个序列最大MEX,即满足
M
E
X
(
p
,
j
)
=
M
E
X
(
p
,
n
)
MEX(p,j)=MEX(p, n)
MEX(p,j)=MEX(p,n)
找到满足这个条件的第一个数字,然后消除前k个数,然后继续递归。
参考
假如是这一个序列 2 2 3 4 0 1 2 0 可以发现选择1 ~ 8和选择1 ~6所得到的结果是一样的,
那么我们就可以直接选择删除的是1 ~ 6
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
int main(){
//freopen("in.txt","r",stdin);
int _;
for(scanf("%d", &_); _; _--){
ll n; cin >> n;
std::vector<ll> arr(n + 1); // 输入n个元素
std::vector<vector<ll> > idx(n + 1); //记录数字x出现的位置分别为多少
for(int i = 0; i < n; i++) {
cin >> arr[i];
idx[arr[i]].push_back(i); //arr[i]出现的位置为i
}
std::vector<ll> res; //存储答案
ll init = 0;
ll mex = 0;
ll cur = -1;
while(init < n){
mex = 0;
cur = init;
//0<=ai<=n
for(int i = 0; i <= n; i++){
auto it = lower_bound(idx[i].begin(), idx[i].end(), init);
//查找init位置上是否有i
if (it == idx[i].end()){
//如果没找到,mex就是i
mex = i;
break;
}
else {
cur = max(*it, cur);
}
}
init = cur + 1; //找下一个位置
res.push_back(mex);
}
cout << res.size() << '\n';
for(int i = 0; i < res.size(); i++) cout << res[i] << " ";
cout << '\n';
}
}
D. Peculiar Movie Preferences
题意
给你n个字符串,每个字符串长度不超过3,问是否能组成回文串
题解
由于字符串长度不超过3,那么可以分类讨论出以下几种情况
- 本身就为回文字符串,例如a,aa,aaa,aba
- 两个子集构成回文串,例如ab和ba,aab和baa
- 两个子集构成回文串,例如ab和cba,或者是abc和ba
注意
2
ab
bad
NO
所以badab是不符合的,即相对顺序不变
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, b) for (int i=a;i<=b;++i)
const int mod = int(1e9) + 7;
const int inf = 0x3f3f3f3f;
const ll inff = 0x3f3f3f3f3f3f3f3fLL;
const double pi = acos(-1.0); //M_PI;
const int maxn = 1e5 + 10;
//给你n个字符串,每个字符串长度不超过3,问是否能组成回文串
int main(){
//freopen("in.txt","r",stdin);
//freopen("aout.txt","w",stdout);
int _;
for(scanf("%d", &_); _; _--){
int n; cin >> n;
bool flag = false;
std::vector<string> arr(n);
multiset<string> suf, pre;//pre记录前面出现的,suf记录后面出现的,TLE5
for(int i = 0; i < n; i++){
cin >> arr[i];
suf.insert(arr[i]);
}
for(int i = 0; i < n; i++){
suf.erase(suf.find(arr[i]));
string now = arr[i];
reverse(now.begin(), now.end());
//aba ab ba
if (suf.count(now)){
flag = true;
break;
}
if (arr[i].size() == 1){
flag = true;
break;
}
if (arr[i].size() == 2){
if (arr[i][0] == arr[i][1]){
flag = true;
break;
}
}
if (arr[i].size() == 3){
if (arr[i][0] == arr[i][2]){
flag = true;
break;
}
}
if (arr[i].size() == 3){
//cb abc
string t1 = arr[i].substr(1, 2);
reverse(t1.begin(), t1.end());
if (pre.count(t1)){
flag = true;
break;
}
//abc ba
string t2 = arr[i].substr(0, 2);
reverse(t2.begin(), t2.end());
if (suf.count(t2)){
flag = true;
break;
}
}
pre.insert(arr[i]);
}
if (flag){
printf("YES\n");
continue;
}
else {
printf("NO\n");
continue;
}
}
}