官方题解|2024新春欢乐赛
2024-03-04 16:02:42
发布于:浙江
T1、新年快乐 - 题解
题面大意
有堆糖果,每次你可以将任意一堆复制到另一堆上。每堆糖果的数量不能超过
题意分析
求最多能复制几次。
解题思路
每次我们把较小的一堆复制到较大的一堆,那么考虑找出最小的一堆,由它来当被复制的,复制到其他堆上。这样每堆能操作的次数才会最多。
时间复杂度解析
找出最小的那堆糖果,扫描所有糖果堆,计算最小糖果堆能复制到其它糖果堆的操作次数,复杂度为
代码演示
#include <bits/stdc++.h>
using namespace std;
const int N = 1100;
int a[N];
int main() {
int n,k;
cin >> n >> k;
for(int i=0;i<n;i++) {
cin >> a[i];
}
sort(a,a+n,less<int>());
int r = 0;
for(int i=1;i<n;i++) {
r += (k - a[i]) / a[0];
}
cout << r << endl;
return 0;
}
T2、新年大扫除 - 题解
题面大意
给你个字符,只由大写字母和组成,每次可以选择个连续的字符,将选中的各个字符变成。
题意分析
找到最小的操作数,将所有的变成
解题思路
每次选择个字符,如果从开始选,则可变的范围就是,考虑只有需要变成,我们可以找到第一个为的字符,从这个字符开始选择个字符变成,然后继续找到下一个。
那么实际上每次我们只需要维护一个值,它表示的字符都能变成
时间复杂度解析
我们只需要遍历一次字符即可,复杂度为
代码演示
#include <bits/stdc++.h>
using namespace std;
int main() {
int n,k;
string s;
cin >> n >> k;
cin >> s;
int r = -1;
int cnt = 0;
for(int i=0;i<s.length();i++) {
if (s[i] == 'O' && i > r) {
cnt ++;
r = i + k - 1;
}
}
cout << cnt << endl;
return 0;
}
T3、新年魔法 - 题解
题面大意
给你两个数字,
每次用较大的数去减去较小的数,如果 那么$ a = a - b $, 不变。
如果两个数字相等,例或皆符合,直到有一个数字小于等于0,就停止运算。
题意分析
问多少次后会停止运算
解题思路
这个操作过程与辗转相减是一样的
如果每次用减法去模拟,当两个数值相差很大时,就要运算很久,我们可以直接用除法去代替减法。
嗯,如果变成除法的话,这与辗转相除法相同。
时间复杂度解析
复杂度与辗转相除法的复杂度等同,
代码演示
#include <iostream>
using namespace std;
int main() {
int a,b;
cin >> a >> b;
int cnt = 0 ;
while(a > 0 && b > 0) {
if (a < b) {
cnt += (b / a);
b %= a;
} else {
cnt += (a / b);
a %= b;
}
}
cout << cnt << endl;
return 0;
}
T4、新年排列 - 题解
题面大意
给你一个长度为的全排列,和一个整数,每次可以任意选择个元素,以升序移动到的末尾,直到为升序。
题意分析
求最小操作次数,使得变为升序
解题思路
找到以1开头的最长上升序子序列,那么不属于部分的则都要移动,将非部分的元素移动到的尾部就好。
时间复杂度解析
我们只需要遍历一次序列,就能找到子序列,复杂度为。
代码演示
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int a[N];
int main() {
int n,k;
cin >> n >> k;
int j = 0;
for(int i=0;i<n;i++) {
cin >> a[i];
if (a[i] == 1) j = i + 1;
}
int l = 1, len = 1;
for(;j<n;j++) {
if (a[j] == l + 1) {
l = l + 1;
len++;
}
}
cout << (n - len) / k + ( (n - len) % k > 0)<< endl;
return 0;
}
T5、新年游戏 - 题解
题面大意
你有个正整数,每次可以选择一对数,与(),然后使 = -
最终会得到一个新的序列
题意分析
要求最终序列的和最小
解题思路
每次我们用一个大的数减去一个小的数,操作后,会变成那个较大的数,会变成那个较小的数字,继续重复这个操作。我们发现与辗转相减的操作是一样的,那么实际上就是求最大公约数。
时间复杂度解析
代码演示
#include <bits/stdc++.h>
using namespace std;
int main() {
int n,r = 0,x;
cin >> n;
for(int i=0;i<n;i++) {
cin >> x;
if (!r) r = x;
r = __gcd(r, x);
}
cout << r * n<< endl;
return 0;
}
T6、新年均馔 - 题解
题面大意
有盒饼干,每盒的饼干数量可能不同,只能从盒子里拿出饼干,问最少拿多少饼干可以使得每盒饼干数量相同。
题意分析
求拿出饼干的最少数量,使得每盒饼干数量相同
解题思路
因为饼干只能拿出,不能放入,如果使得每盒饼干数量相同,根据木桶原理,那么最终每盒饼干的数量一定等于饼干数量最少的那盒。
时间复杂度解析
我们只需要遍历所有饼干,算这盒饼干与数量最少的那盒饼干的差值就行,复杂度为。
代码演示
#include <bits/stdc++.h>
using namespace std;
const int N = 100;
int a[N];
int main() {
int n;
cin >> n;
int x = 0xfffffff;
for(int i=0;i<n;i++) {
cin >> a[i];
x = min(x, a[i]);
}
int r = 0;
for(int i=0;i<n;i++) {
if (a[i] > x) r += (a[i] - x);
}
cout << r << endl;
return 0;
}
T7、新年花坛守护战 - 题解
题面大意
现在有个花坛,每个花坛上有个小年兽,你需要驱赶所有的小年兽。
有两种驱赶的方案
幸运福花:消费 金币可以驱赶一个小年兽
烟花炮:消费 个 金币,可以驱赶任意一个花坛上的所有小年兽
题意分析
请问最少花费多少个金币,就可以将小年兽全部驱赶呢?
解题思路
每个花坛只要选择一种方案就行了,然后我们要看是选择幸运福花还是烟花炮,如果某一个花坛上的小年兽数量是小于烟花炮需要的金币数量,那么就选择幸运福花驱赶这个花坛上所有的小年兽,反之选择烟花炮。
时间复杂度解析
遍历所有花坛,进行分析即可,复杂度为。
代码演示
#include <bits/stdc++.h>
using namespace std;
const int N = 110;
int a[N];
int main() {
int n,c,k;
cin >> n >> c;
for(int i=0;i<n;i++) {
cin >> a[i];
};
int r = 0;
for(int i = 0;i<n;i++) {
int x = a[i];
if (x >= c) {
r += c;
} else r+=x;
}
cout << r << endl;
return 0;
}
T8、新年红包 - 题解
题面大意
有个数字,只有一个数字出现了一次,其他数字都出现了两次。
题意分析
求出现一次的那个数字
解题思路
用异或去消除两两出现的数字,剩下那个就是出现一次的数字
时间复杂度解析
遍历所有数字,复杂度为
代码演示
#include <bits/stdc++.h>
using namespace std;
int main() {
int n,a,r = 0;
cin >> n;
for(int i=0;i<n;i++) {
cin >> a;
r ^= a;
}
cout << r << endl;
return 0;
}
T9、新年糖果 - 题解
题面大意
给你一个数,可以被分成个数相加,数的取值为
题意分析
问最多能被分成几个$ n \times 2 $
解题思路
因为题面告诉我们这个数,最多只能被分成个,所以答案的最大值为。
再看一下里面有多少个$ n \times 2 $就可以
时间复杂度解析
求得能被分成几个$ n \times 2 $,用除法就行。复杂度为:
代码演示
#include <bits/stdc++.h>
using namespace std;
int main() {
long long t,n,s;
cin >> n >> s;
cout << s / (2 * n) << endl;
return 0;
}
T10、新年消消乐 - 题解
题面大意
给你 个数,两个数字相加如果是奇数则消除,且一个数只能被使用一次
题意分析
是否所有数都能被消除。
解题思路
一个偶数加上一个偶数还是一个偶数,一个奇数加上一个奇数会变成偶数,一个奇数加上一个偶数才会是奇数。
所以,统计奇数与偶数的数量是否相等即可。
时间复杂度解析
遍历所有数统计数量即可,复杂度为。
代码演示
#include <bits/stdc++.h>
using namespace std;
const int N = 120;
int arr[N];
int main() {
int n,k;
cin >> n;
int x = 0,y = 0;
for(int i=0;i<n*2;i++) {
cin >> k;
if (k & 1) x++;
else y++;
}
if (x == y) {
cout << "YES" << endl;
} else {
cout << "NO" << endl;
}
return 0;
}
全部评论 4
新年快乐
2024-02-18 来自 浙江
2新年快乐
2024-02-18 来自
2挑战赛是这周末吗?
2024-02-19 来自
0
新年快乐!!!
2024-02-19 来自 浙江
1新年快乐
2024-02-18 来自 上海
1
有帮助,赞一个