A题: Maximize?
题目大意:
给你一个整数 x, 要求你找出任意一个 y ,。使得最大。
思路一:暴力
数据范围小,直接暴力。
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
void solve() {int x; cin >> x;int res = 0, id = 1;for (int y = 1; y < x; y ++ ) {if (__gcd(x, y) + y > res) {res = __gcd(x, y) + y;id = y;}}cout << id << endl;
}
signed main() {ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int tt; cin >> tt;while (tt -- ) solve();return 0;
}
思路二 :动脑子
我们只要令 y = x - 1,那么就可以使得原式子的值为 x。
所以输出 x - 1即可。
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
void solve() {int x; cin >> x;cout << x - 1 << endl;
}
signed main() {ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int tt; cin >> tt;while (tt -- ) solve();return 0;
}
B题: Prefiquence
题目大意:
给你两个二进制字符串 𝑎 和 𝑏 。二进制字符串是由字符 "0 "和 "1 "组成的字符串。
您的任务是确定最大可能的数字 𝑘 ,使得长度为 𝑘 的字符串 𝑎 的前缀是字符串 𝑏 的子序列。
思路:贪心
如果b中的要取出来跟a的前缀去匹配,那么是不是越早出现越好?
这样就可以让后面空出更多能够跟a去匹配了。
双指针,时间复杂度
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
void solve() {int n, m; cin >> n >> m;int j = 0, ans = 0;string a, b; cin >> a >> b;for (int i = 0; i < n; i ++ ) {while (j < m && b[j] != a[i]) j += 1;if (j == m) break;ans += 1, j += 1;}cout << ans << endl;
}
signed main() {ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int tt; cin >> tt;while (tt -- ) solve();return 0;
}
C题: Assembly via Remainders
题目大意:
给你一个数组 。你的任务是找出任意一个数组 ,其中:
- 1≤≤ 代表所有 1≤𝑖≤𝑛 。
- %
思路:
我们要构造,如果比大的话,根据模的计算,我们是不是可以就直接放入了?
那我们每次构造出的,都让它等于,让数组a一直递增,是不是就符合要求了?
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
void solve() {int n; cin >> n;vector<int> res;int last = 600;res.push_back(last);for (int i = 1; i < n; i ++ ) {int x; cin >> x;res.push_back(res[i - 1] + x);}for (auto c : res) cout << c << ' ';cout << endl;
}
signed main() {ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int tt; cin >> tt;while (tt -- ) solve();return 0;
}
D题: Permutation Game
题目大意:
见链接。
思路:
如果我们站的位置是最大的,那么我们就不需要移动了对吧,因为可以一直站在上面得到最大的分数。
否则我们就去下一个位置去看看,能不能获得更多的得分。
遍历的话因为是排列,移动是一个环,所以我们最多的遍历次数是 n
用了set避免重复绕环
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
void solve() {int n, k, pb, ps; cin >> n >> k >> pb >> ps;vector<int> p(n + 1), a(n + 1);int maxv = -1;for (int i = 1; i <= n; i ++ ) cin >> p[i];for (int i = 1; i <= n; i ++ ) cin >> a[i];for (int i = 1; i <= n; i ++ ) if (maxv > a[i]) maxv = a[i];int score1 = k * a[pb], score2 = k * a[ps];int now1 = score1, now2 = score2;int cnt = 0;unordered_set<int> f1;while (a[pb] != maxv && cnt < k) {cnt += 1;now1 -= (k - cnt) * a[pb];f1.insert(pb);pb = p[pb];if (f1.count(pb)) break;now1 += (k - cnt) * a[pb];score1 = max(score1, now1);}cnt = 0;f1.clear();while (a[ps] != maxv && cnt < k) {cnt += 1;now2 -= (k - cnt) * a[ps];f1.insert(ps);ps = p[ps];if (f1.count(ps)) break;now2 += (k - cnt) * a[ps];score2 = max(score2, now2);}if (score1 > score2) cout << "Bodya\n";else if (score1 == score2) cout << "Draw\n";else cout << "Sasha\n";
}
signed main() {ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int tt; cin >> tt;while (tt -- ) solve();return 0;
}
E题: Cells Arrangement
题目大意:
在 n x n 的方格中找到 n 个点,使得它们之间的曼哈顿距离种类最多。
思路:
我们发现样例中有连起来一块的,还有斜着放着的。
可证:先放(1, 1), 再放(1, 2),最后全部斜着放是能取完所有的距离情况的,这是最大,符合要求。
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
void solve() {int n; cin >> n;cout << "1 1" << endl;cout << "1 2" << endl;for (int i = 3; i <= n; i ++ ) {cout << i << ' ' << i << endl;}
}
signed main() {ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int tt; cin >> tt;while (tt -- ) solve();return 0;
}
G1:Division + LCP (easy version)
题目大意:
见链接。
思路:
极其类似砍木头,是二分答案。
每次我们去找字符串 mid 个长度的前缀在整个字符串中的出现次数,
如果大于等于 k,那么 l = mid,否则 r = mid
找的过程(不会Z函数),用了KMP,
时间复杂度
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
vector<int> nt;
void build(string &s) {int n = s.size();vector<int> pi(n);for (int i = 1; i < n; i ++ ) {int j = pi[i - 1];while (j > 0 && s[i] != s[j]) j = pi[j - 1];if (s[i] == s[j]) j += 1;pi[i] = j;}nt = pi;
}
int KMP(string &t, string &s) {build(s);int n = t.size(), m = s.size(), j = 0;int last = -1e9, ans = 0;for (int i = 0; i < n; i ++ ) {while (j > 0 && t[i] != s[j]) j = nt[j - 1];if (t[i] == s[j]) j += 1;if (j == m) {int head = i - m + 1;if (head >= last + m) {ans += 1;last = head;}}}return ans;
}
void solve() {int n, k; cin >> n >> k >> k;string s; cin >> s;int l = 0, r = n / k + 1;while (l + 1 != r) {int mid = l + r >> 1;string p = s.substr(0, mid);if (KMP(s, p) >= k) l = mid;else r = mid;}cout << l << endl;
}
signed main() {ios::sync_with_stdio(0);cin.tie(0); cout.tie(0);int tt; cin >> tt;while (tt -- ) solve();return 0;
}