A. King Keykhosrow's Mystery
思路:看懂题后知道只要求他们的最小公倍数就行了,而难点就在于对其的证明。(搜了一下好像没人讲证明过程,这里我斗胆讲一下)。
证明:
首先列出m成立的两个条件逐一分析:
条件一:m 必须大于或等于 𝑎 和 𝑏 中的至少一个。
解释:保证了题目有意义,不然m可以很小,同时小于a、b,比如1、2,等的对他们的余数都相等,所以要有此条件。
条件二:𝑚 除以 𝑎 的余数必须等于 𝑚 除以 𝑏 的余数。
解释:这可以通过数学上的同余关系来理解。列出下列式子:
公式一:
公式二:
其中 𝑘 和 𝑙 是整数,𝑟 是余数。这意味着 𝑚 可以被 𝑎 和 𝑏 的某个公倍数表示,且余数相同。 那么我们要最小的m,肯定是余数 𝑟 为0,那么公式简化完不就是m是a,b的倍数,最小不就是最小公倍数。
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
int gcd(int a, int b){
if(b == 0) return a;
return gcd(b, a % b);
}
int lcm(int a, int b){
return (a / gcd(a, b)) * b;
}
void solve() {
int a, b;
cin >> a >> b;
int l = lcm(a, b);
cout << l << endl;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
solve();
}
return 0;
}
还有一种暴力做法,从a、b的较小值开始遍历,直到满足条件为止,这题数据范围较小,能过。
B. Rakhsh's Revival
思路:贪心,从头开始遍历,遇到不满足的区间就+1。
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
int n, m, k;
cin >> n >> m >> k;
string s;
cin >> s;
int num = 0, res = 0;
for (int i = 0; i<n; i++){
if (s[i]=='1') num = 0;
else if (s[i]=='0'){
num++;
if (num >= m){
res++;
num = 0;
i+=k-1;
}
}
}
cout << res << endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
C. Trapped in the Witch's Labyrinth
思路:感觉会有更好的思路,这里我讲一下我的思路。我主要想的是用两次dfs。第一次把能跑出去的都记录下来,check标为1,不能跑出来的标0(包括遇到'?'未知的地方);第二次遍历check为0的地方,如果是已知地方那么肯定要+1,如果是'?'未知地方,那么检查它的上下左右四个方向是否存在有不能走通的方向,如果有就+1,如果四个方向都能走通(check为1),那么跳过。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int dx[4] = {1, 0, 0, -1};
int dy[4] = {0, 1, -1, 0};
void solve() {
ll n, m;
cin >> n >> m;
vector<vector<char>> g(n, vector<char>(m));
vector<vector<bool>> vis(n, vector<bool>(m, false));
vector<vector<int>> check(n, vector<int>(m, 0));
for (ll i = 0; i < n; i++) {
for (ll j = 0; j < m; j++) {
cin >> g[i][j];
}
}
function<bool(int, int)> dfs = [&](int x, int y) -> bool {
if (x < 0 || x >= n || y < 0 || y >= m) {
return 1;
}
if (vis[x][y]) {
return check[x][y];
}
if (g[x][y] == '?') return 0;
vis[x][y] = true;
if (g[x][y] == 'U') check[x][y] |= dfs(x-1, y);
else if (g[x][y] == 'D') check[x][y] |= dfs(x+1, y);
else if (g[x][y] == 'L') check[x][y] |= dfs(x, y-1);
else if (g[x][y] == 'R') check[x][y] |= dfs(x, y+1);
return check[x][y];
};
for (ll i = 0; i < n; i++) {
for (ll j = 0; j < m; j++) {
if (!vis[i][j]) {
dfs(i, j);
}
}
}
// for (ll i = 0; i < n; i++) {
// for (ll j = 0; j < m; j++) {
// cout << check[i][j] << " \n"[j==m-1];
// }
// }
int ans = 0;
for (int i = 0; i<n; i++)
{
for (int j = 0; j<m; j++){
if (check[i][j] == 0 && g[i][j]!='?'){
ans++;
}
else if (check[i][j] == 0 && g[i][j] == '?'){
int pp = 1;
for (int k = 0; k<4; k++){
int tx = i+dx[k], ty = j+dy[k];
if (tx >= 0 && tx <n && ty >=0 && ty < m){
pp&=check[tx][ty];
}
}
if (pp == 0) ans++;
}
}
}
cout << ans << endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t--) {
solve();
}
return 0;
}
这里我保留了输出check数组的注释,感兴趣的可以试一下。
D. Darius' Wisdom
思路:题意很好懂,简单的思维在代码量上还是很大的。
这里我们知道如果应该是2的位置上为0,需要2次操作,为1,需要一次操作,应该为1的位置上是0的话需要一次操作。这里其实用到了了贪心,我们肯定从二位置的上来开始弄,因为他会影响0,1的位置,再严谨得写代码。
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
int n, m, k;
cin >> n;
vector<int> a(n);
for (int i = 0; i<n; i++){
cin >> a[i];
}
array<set<int>, 3> pos;
for (int i = 0; i<n; i++) pos[a[i]].emplace(i);
vector<pair<int, int>> ans;
auto modify = [&](int i){
if (!pos[2].empty()){
if (a[i] == 2) pos[2].erase(i);
else if (a[i] == 1){
int temp = *pos[2].begin();
swap(a[i], a[temp]);
pos[2].erase(temp);
pos[1].erase(i);
pos[1].emplace(temp);
ans.emplace_back(i, temp);
}
else {
int tem1 = *pos[1].begin(), tem2 = *pos[2].begin();
swap(a[i], a[tem1]);
swap(a[i], a[tem2]);
pos[2].erase(tem2);
pos[1].erase(tem1);
pos[1].emplace(tem2);
pos[0].erase(i);
pos[0].emplace(tem1);
ans.emplace_back(i, tem1);
ans.emplace_back(i, tem2);
}
}
else{
if (a[i] == 1) pos[1].erase(i);
else{
int temp = *pos[1].begin();
swap(a[i], a[temp]);
pos[1].erase(temp);
pos[0].erase(i);
pos[0].emplace(temp);
ans.emplace_back(i, temp);
}
}
};
for (int i = n-1; i>=0; i--){
if (pos[1].empty() && pos[2].empty()) break;
modify(i);
}
cout << ans.size() << endl;
for (auto [fi, se] : ans){
cout << fi+1 << " " << se+1 << endl;
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
(如果有帮助请点赞或评论支持,有问题请指正,其他问题请评论交流...)
都看到这里了真不点个赞吗