A题: Contest Proposal
题目大意:
给你一个大小为 n 的数组 a 和数组 b,你可以进行下列操作若干次--在数组 a 的任意位置插入一个数字(要求插入后数组 a 还是升序的,每次插入一个数 a 就会弹出末尾的最大那个数)。
问:至少需要多少次操作才能使得 中的每一个i, 。
思路:
题目的意思是不是我们利用上更多的 a 中原来有的元素,这样答案才会更小?
对于一个 ,如果能找到一个 ( 是大于等于其的,那就可以说它是可以利用上的,这样就能少插入一个。
用了双指针,因为要比较。
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int tt; cin >> tt;
while (tt -- ) {
int n; cin >> n;
vector<int> a(n), b(n);
for (int i = 0; i < n; i ++ ) cin >> a[i];
for (int i = 0; i < n; i ++ ) cin >> b[i];
int now = 0, ans = 0;
for (int i = 0; i < n; i ++ ) {
if (a[i] <= b[now]) {
now += 1;
}else {
while (a[i] > b[now] && now < n) {
ans += 1;
now += 1;
}
if (now == n) break;
now += 1;
if (now == n) break;
}
}
cout << ans << endl;
}
return 0;
}
B题:Coin Games
题目大意:
n枚硬币围成一个圈,每个硬币有面朝上和面朝下两种状态。每当轮到一名玩家时,玩家取出一枚面朝上的硬币,并且将其两旁的硬币改变面的朝向,当没有硬币可以取时游戏结束(没有面朝上的或者全取完了),轮到的玩家失败。问先手的胜负情况。
思路:
有这么几种情况(取法)
DUD -->操作后U的数量会+1
DUU -->操作后U的数量会-1
UUU -->操作后U的数量会-3
所以,在操作的过程中U的数量是奇偶变化的,所以我们只要遍历一遍字符串,如果U的数量是奇数,那么先手在操作过程中遇到的状态都是奇数,也就是必胜。反之,一定必败。
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int tt; cin >> tt;
while (tt -- ) {
int n; cin >> n;
string s; cin >> s;
int cnt = 0;
for (auto c : s) {
if (c == 'U') {
cnt += 1;
}
}
if (cnt & 1) cout << "YES\n";
else cout << "NO\n";
}
return 0;
}
C题: Permutation Counting
题目大意:
你有 n 种纸牌,每张纸牌上标有的数字。
标有 i 数字的纸牌的数量由数组 表示。
要求你使用你得到的纸牌,构造出一个数组,数组中每个连续的,大小为 n 的子数组(数组中的元素对应的数字每个都出现一次)就能使你的得分加1,要求你输出你的最大化得分。
思路:
一:短板效应
给出这么一个例子。
5 0
0 999 999 999 999
首先你肯定会说,这是构不成[1, 2, 3, 4, 5]的,所以得分是0。
然后如果是
5 0
1 999 999 999 999
先不管答案,但是你的最大化得分一定受到了这个1的影响。
所以,如果可以,你会将你的coin(题目中的k)加到这个1上面来提高你的得分。
二:加到哪个数字上去
由上述分析可知 ,你的得分会受到最小的数的影响。
如果你不加到最小的数上去,最大的得分并不会因此而改变。
因为如果你按最优化构造,最小的数肯定是已经和充分与其它数组合在一起了,加到其他地方上的数就变成了多余的。
所以我们的 k 一定是先用来抬高最小值的。
三:多出来的 k
样例一
2 4
8 4
添加之后从 8 4 -> 8 8
n表示种类,就是题目中得那个n
m表示符合题意得子数组的数量,这里是8,因为能构造出8个
算得答案为15,正确
其余样例可以根据上述思路进行验证,在此不一一赘述。
如果我们构造完了,构造出了这个
1 2 3 .... n
n位置上是出现次数最少的那一个数
那是不是我们还有办法在后面加?
如果还剩一个 4 的话
4 1 2 3 ... n 4
还剩 4 3的话
4 3 1 2 .. n 4 3
懂我意思了嘛?qwq
就是说,构造完剩下来的数,你还是可以放到后面去使得答案加1,多出来9个1,还是使得答案+1,那8个就是没用的了。
所以:
抛开和最小值构成的子数组,其他种类数都可以有办法再添加到数组后面去一个,
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int tt; cin >> tt;
while (tt -- ) {
int n, k; cin >> n >> k;
vector<int> a(n + 1), pre(n + 1);
for (int i = 1; i <= n; i ++ ) cin >> a[i];
sort(a.begin() + 1, a.end());
for (int i = 1; i <= n; i ++ ) {
pre[i] = pre[i - 1] + (a[i] - a[i - 1]) * (i - 1);
}
int l = 0, r = n + 1;
while (l + 1 != r) {
int mid = l + r >> 1;
if (pre[mid] <= k) l = mid;
else r = mid;
}
k -= pre[l];
int res = n * (a[l] + k / l - 1) + 1;
k %= l;
res += k + (n - l);
cout << res << endl;
}
return 0;
}
代码解释:
是可以不用二分的,但是不知道为什么就用上了。
这个只跟数量有关,先sort。
这样二分出来的 l表示前 l 个数都可以在k的代价以内变成a[l]
n是种类
在k的代价以内都可以变成a[l],说明现在的最小值就是a[l]
子数组个数为 个,这样最大化最小值了。
然后多余的可以放在后面,是 n - l个多余的种类,还有k%l个多余的。
D1题: Reverse Card (Easy Version)
题目大意:
问有多少组使得是的倍数
思路:
暴力。
hint:这个a是不是一定是b的倍数呀?
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int tt; cin >> tt;
while (tt -- ) {
//a+b是b⋅gcd(a,b)的倍数。
int n, m; cin >> n >> m;
int ans = 0;
for (int b = 1; b <= m; b ++ ) {
int a = b;
while (a <= n) {
if ((a + b) % (b * b) == 0) ans += 1;
a += b;
}
}
cout << ans << endl;
}
return 0;
}