A题:小红的字符串
题意
给定一个长度为3的字符串,小红每次可以修改其中一个字符为任意,问使得三个字符相同的最少操作次数
思路
大水题
变的越少越好,我们只需统计字符数量,取变的最少的即可
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int> a(26);
string s; cin >> s;
int ans = 3;
for (int i = 0; i < 3; i ++ ) {
a[s[i] - 'a'] += 1;
ans = min(ans, 3 - a[s[i] - 'a']);
}
cout << ans << endl;
return 0;
}
B题:小红的序列乘积
题意
定义fi为前i相的乘积,问i从1到n,有几个fi的个位数为6
思路
最后乘积的个位数只与每次相乘两数的个位数有关
所以我们只需看每个数的个位数即可
当乘起来为6时,答案加加即可
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int n; cin >> n;
int cur = 1, ans = 0;
for (int i = 0; i < n; i ++ ) {
string s; cin >> s;
int now = s.back() - '0';
cur = now * cur % 10;
if (cur == 6) ans += 1;
}
cout << ans << endl;
return 0;
}
C题:小红的数组重排
题意
给定一个长度为n的数组a,要求你进行重新排序,满足题目要求
思路
对于相邻两项我们可以进行消去,发现要求构造的数组奇数项和偶数项都要求单增。所以我们要避免一个数出现3次的情况,因为出现3次,肯定有两个在奇数项或者偶数项,单增不了。
但是,特别地,我们要注意0的情况,上述消去基于不是0的标准。
0的情况下,只要出现两个就满足不了题意
代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int n; cin >> n;
vector<int> a(n);
map<int, int> cnt;
bool ok = true;
for (int i = 0; i < n; i ++ ) {
cin >> a[i];
if (++ cnt[a[i]] == 3 - (a[i] == 0)) ok = false;
}
cout << (ok ? "YES" : "NO") << endl;
sort(a.begin(), a.end());
for (int i = 0; i < n; i += 2) {
cout << a[i] << ' ';
if (i + 1 < n) cout << a[i + 1] << ' ';
}
cout << endl;
return 0;
}
D题:虫洞操纵者
题意
迷宫+遇到墙可以进行穿梭
思路
还是bfs,数据是1e3,所以我们遍历整个图是1e6,对于穿梭操作,我们直接进行暴力1e3,总的就变成1e9,不会T。况且1e9是极限情况,不可能每个点都需要遍历1e3的
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1010;
int vis[N][N], d[N][N];
int dx[] = {-1, 0, 1, 0}, dy[] = {0, -1, 0, 1};
int main() {
int n; cin >> n;
vector<vector<int>> a(n + 2, vector<int>(n + 2, 1));
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ ) {
cin >> a[i][j];
}
queue<int> q;
q.push(10001);
vis[1][1] = 1;
while (q.size()) {
int x = q.front() / 10000, y = q.front() % 10000;
q.pop();
for (int i = 0; i < 4; i ++ ) {
int xn = x + dx[i], yn = y + dy[i];
if (a[xn][yn]) {
int dir = (i + 2) % 4;
int j = 1;
while (!a[x + dx[dir] * j][y + dy[dir] * j]) j += 1;
xn = x + dx[dir] * (j - 1), yn = y + dy[dir] * (j - 1);
}
if (vis[xn][yn]) continue;
vis[xn][yn] = 1, d[xn][yn] = d[x][y] + 1;
q.push(xn * 10000 + yn);
}
}
cout << (vis[n][n] ? d[n][n] : -1) << endl;
return 0;
}
E题:小红的序列乘积2.0
题意
见题目
思路
我们考虑每一个点对于答案的贡献
首先一定是乘起来个位数是6才能加上答案
而对于前面点的情况,我们并不知道,所以可以用一个数组来储存前面i-1个数非空子序列乘积的个位数的情况
然后我们用a[i]去对前面1~9的可能情况进行遍历,如果可以为6,那么对于后面的n-i个数,无论怎么取,都可以使得答案增加1,而后面取的情况是Cx0 + Cx1 + ... + Cxx,是2的x次
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll mod = (ll)1e9 + 7;
inline ll qmi(ll a, ll b) {
ll res = 1;
while (b) {
if (b & 1) res = res * a % mod;
b >>= 1;
a = a * a % mod;
}
return res % mod;
}
int main() {
int n; cin >> n;
vector<ll> a(10);
ll ans = 0;
a[1] = 1;
for (int i = 1; i <= n; i ++ ) {
vector<ll> backup = a;
string s; cin >> s;
int x = s.back() - '0';
for (int j = 1; j < 10; j ++ ) {
int cur = x * j % 10;
backup[cur] = (backup[cur] + a[j]) % mod;
if (cur == 6) ans = (ans + a[j] * qmi(2, n - i) % mod) % mod;
}
a = backup;
}
cout << ans << endl;
return 0;
}