猜拳游戏
题意 石头剪刀布游戏,对方会告诉每次将要出的手势,但是对方永远希望自己赢所以会欺骗,你要出什么手势才能赢
题解 对方说什么,就出什么
#include <iostream>
using namespace std;
int main() {
string s; cin >> s;
cout << s << endl;
return 0;
}
Kevin喜欢一
题意 开始时候输入框只有一个 1
,每次可以选中字符复制一份,问最少操作次数能够使得恰好有 n
个 1
#include <iostream>
using namespace std;
int main() {
int T; cin >> T;
while (T --) {
int n; cin >> n;
int l = 0, r = 31;
while (l < r) {
int mid = l + r >> 1;
if ((1 << mid) >= n) r = mid;
else l = mid + 1;
}
cout << l << endl;
}
return 0;
}
A加B,A模B
题意 已知 a + b = n
和 a mod b = m
,给定 n
和 m
求解 a
和 b
,
题解 首先有以下化简
a = n - b
a = b * k + m
n - b = b * k + m
n - m = b * (k + 1)
因为 a = b * k + m
,而 a >= 0, b >= 1, m >= 0
,所以 k >= 0
因为 b > 1, k >= 0
,所以 n - m > 0
,若不符合输出 -1
因为 a mob b = m
,因此 b > m
,在式 n - m = b * (k + 1)
得 b = (n - m) / (k + 1)
,因此要使得 b > m
更可能成立,而 n - m
已是定值,所以要使 k + 1
尽可能小,即 k = 0
时,b = n - m
,则 a = m
,由 b > m
得 n - m > m
则 n > 2 * m
,若不成立则输出 -1
#include <iostream>
using namespace std;
void solve() {
int n, m; cin >> n >> m;
if (n - m < 1 || n <= m * 2) {
cout << -1 << endl;
return;
}
cout << m << ' ' << n - m << endl;
}
int main() {
int T; cin >> T;
while (T --) solve();
return 0;
}
MoonLight的运算问题
题意 最初有一个数字 0
,每次给定一个数字 a[i]
,进行下列俩操作之一,并删除该数,后续数字往前挪,序号 -1
,输出最大值 mod 998244353
- x = x ∗ a [ i ] x = x * a[i] x=x∗a[i]
- x = x + a [ i ] x = x + a[i] x=x+a[i]
题解 如果 res >= 2
则进行的操作一定是乘法,否则相加,要标记一下 res
是否已经大于等于 2
#include <iostream>
using namespace std;
typedef long long ll;
const int mod = 998244353;
int solve() {
ll res = 0;
int n; cin >> n;
bool flag = true;
while (n --) {
int x; cin >> x;
if (x < 2 || flag) res = res + x;
else res = res * x;
if (res > 1) flag = false;
res %= mod;
}
return res;
}
int main() {
int T; cin >> T;
while (T --) cout << solve() << endl;
return 0;
}
括号序列操作专家
题意 给定一个括号序列,每次可以交换相邻的两个括号,求至少需要多少次操作才能使得原来的括号串合法
#include <iostream>
using namespace std;
int solve() {
int n; string s; cin >> n >> s;
long long res = 0, l = 0, r = 0;
for (int i = 0; i < n; i ++) {
if (s[i] == '(') {
if (l < r) res += r - l;
l ++;
} else r ++;
}
if (l != r) res = -1;
return res;
}
int main() {
int T; cin >> T;
while (T --) cout << solve() << endl;
return 0;
}
Kevin的矩阵
题意 给定 n
长度的 a
序列,和一个初始 m
列的空矩阵,将 a
序列依次填入,求最少次数能使得一列全为目标值 k
每次操作他可以从下面的操作中任选其一:
- 任选序列的某个位置,将此位置的数字修改为任意的数字
- 将矩阵的列数增加
1
- 将矩阵的列数减小
1
,合法的前提下
题解 最坏情况是 m = 1
,需要将 m
变为 sqrt(n)
,然后加上 sqrt(n)
(可能是 sqrt(n) + 1
的行数),故最大波动范围是 [n - 2 * sqrt(n) - 1, n + 2 * sqrt(n) + 1]
,然后枚举取最小值即可
#include<iostream>
#include<cmath>
using namespace std;
const int N = 2e5 + 2;
int a[N];
int main() {
int T; cin >> T;
while (T --) {
int n, m, g, ans = 0, num = 4e5;
cin >> n >> m >> g;
for (int i = 1; i <= n; i++) cin >> a[i];
int s = 2 * sqrt(n);
for (int i = max(m - s, 1); i <= min(s + m, n); i ++) {
for (int j = 1; j <= i; j ++) {
ans = 0;
for (int k = j; k <= n; k += i)
if (a[k] != g) ans ++;
num = min(num, abs(i - m) + ans);
}
}
cout << num << endl;
}
}