寒假训练2024/2/14
紫书
uva10285
题意:
给r行c列的数字,求最长的上升序列。
思路:
起初我以为是dp,但是对于路径的更新还与方向有关,比如同样是从左向右更新,12345和54321得出来的值不同(我的dp是本格由上下左右四格dp来的,如果值满足大小关系,取最大值)
所以我们考虑搜索,也就是深搜,看一眼复杂度,$n^2 * n^2$ 这样1e8的复杂度应该过不了,我们用记忆化优化:同一条路径,如果一个点被搜过了,那就不用搜了,除非有以更大的贡献值搜索该点。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int arr[105][105];
int vis[105][105];
int r, c;
int ans = 0;
int dx[] = {0, 0, 1, -1};
int dy[] = {1, -1, 0, 0};
void f(int x, int y, int cnt) {
ans = max(ans, cnt);
vis[x][y] = cnt;
for (int i = 0; i < 4; i++) {
int tx = x + dx[i];
int ty = y + dy[i];
if(tx >= 0 && tx < r && ty >= 0 && ty < c && arr[x][y] < arr[tx][ty] && vis[tx][ty] <= vis[x][y]) {
f(tx, ty, cnt + 1);
}
}
}
void solve() {
string _name;
cin >> _name >> r >> c;
ans = 0;
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
cin >> arr[i][j];
vis[i][j] = 0;
}
}
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if(vis[i][j]) {
continue;
}
f(i, j, 1);
}
}
cout << _name << ": ";
cout << ans << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while(T--) {
solve();
}
return 0;
}
codeforcediv3 925
太菜了,f看半天没出
A. Recovering a Small String
思路:
后面的字母尽可能大,前面的字母自然就小
分三种情况三个位置出现z的取值范围
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n;
cin >> n;
if(n <= 27) {
cout << "aa" << (char)('a' + n - 3) << endl;
}
else if(n <= 52) {
cout << "a" << (char)('a' + n - 2 - 26) << "z\n";
}
else {
cout << (char)('a' + n - 53) << "zz\n";
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T = 1;
cin >> T;
while(T--) {
solve();
}
return 0;
}
B. Make Equal
思路:
一眼前缀和
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n;
cin >> n;
vector<int>v(n);
int sum = 0;
for (int i = 0; i < n; i++) {
cin >> v[i];
sum += v[i];
}
int avg = sum / n;
int t = 0;
bool ok = 1;
for (auto it : v) {
t += it - avg;
if(t < 0) {
ok = 0;
break;
}
}
if(ok) {
cout << "YES\n";
}
else {
cout << "NO\n";
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T = 1;
cin >> T;
while(T--) {
solve();
}
return 0;
}
C. Make Equal Again
思路:
分三种情况,前面一块,后面一块和中间一块
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n;
cin >> n;
vector<int>v(n);
for (int i = 0; i < n; i++) {
cin >> v[i];
}
if(v[0] == v.back()) {
int num = 0;
int pb = 0;
while(v[pb] == v[0]) {
pb++;
num++;
}
pb = n - 1;
while(v[pb] == v[0]) {
pb--;
num++;
}
cout << max(0ll, n - num) << endl;
}
else {
int num1 = 0, num2 = 0;
int pb = 0;
while(v[pb] == v[0]) {
pb++;
num1++;
}
pb = n - 1;
while(v[pb] == v.back()) {
pb--;
num2++;
}
cout << min(n - num1, n - num2) << endl;
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T = 1;
cin >> T;
while(T--) {
solve();
}
return 0;
}
D. Divisible Pairs
思路:
哈希。
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n, x, y;
cin >> n >> x >> y;
int res = 0;
map<pair<int, int>, int> mp;
for (int i = 0, t; i < n; i++) {
cin >> t;
int a, b, na, nb;
a = t % x;
b = t % y;
na = (x - a) % x;
nb = b;
res += mp[{na, nb}];
mp[{a, b}]++;
}
cout << res << endl;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T = 1;
cin >> T;
while(T--) {
solve();
}
return 0;
}
E. Anna and the Valentine's Day Gift
思路:
这个题的本质是每个数的后置零的数量,统计一下找规律就很好做。
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve() {
int n, m;
cin >> n >> m;
vector<int>v;
int sum = 0;
for (int i = 0; i < n; i++) {
int t;
cin >> t;
int nt = t;
while(nt) {
nt /= 10;
sum++;
}
int cnt = 0;
while(t % 10 == 0) {
cnt++;
t /= 10;
}
if(cnt) {
v.push_back(cnt);
}
}
sort(v.begin(), v.end(), greater());
for (int i = 0; i < v.size(); i += 2) {
sum -= v[i];
}
if(sum <= m) {
cout << "Anna\n";
}
else {
cout << "Sasha\n";
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T = 1;
cin >> T;
while(T--) {
solve();
}
return 0;
}