A - Cyclic
三位正整数abcabcabc,输出bcabcabca和cabcabcab
# -*- coding: utf-8 -*-
# @time : 2023/6/2 13:30
# @file : atcoder.py
# @software : PyCharm
import bisect
import copy
import sys
from itertools import permutations
from collections import defaultdict, Counter, deque
from functools import lru_cache, cmp_to_key
import heapq
import math
sys.setrecursionlimit(100010)
def main():
items = sys.version.split()
fp = open("in.txt") if items[0] == "3.10.6" else sys.stdin
s = fp.readline().strip()
s0 = s[1] + s[2] + s[0]
s1 = s[2] + s[0] + s[1]
print(s0, s1)
if __name__ == "__main__":
main()
B - Strawberries
字符串ooxxx代表牙齿,其中o代表健康的牙齿。
当有连续的k颗健康牙齿时,可以吃掉一颗草莓。问最多能吃几个草莓。
记录一个cnt,用于维护连续的牙齿数
# -*- coding: utf-8 -*-
# @time : 2023/6/2 13:30
# @file : atcoder.py
# @software : PyCharm
import bisect
import copy
import sys
from itertools import permutations
from collections import defaultdict, Counter, deque
from functools import lru_cache, cmp_to_key
import heapq
import math
sys.setrecursionlimit(100010)
def main():
items = sys.version.split()
fp = open("in.txt") if items[0] == "3.10.6" else sys.stdin
n, k = map(int, fp.readline().split())
s = fp.readline().strip()
ans = 0
o = 0
for i in range(n):
if s[i] == 'O':
o += 1
else:
ans += o // k
o = 0
ans += o // k
print(ans)
if __name__ == "__main__":
main()
C - Sowing Stones
在一列格子里面有m个位置存着石头,每个位置xix_ixi里有aia_iai个石头。石头只能往右边移动,最后需要让每个格子里有一个石头。
问1.是否可能,2.需要几步。
从右往左遍历一遍,看对于每个i是否满足ai+ai+1+...≤(n−xi+1)a_i+a_{i+1}+... \leq (n-x_i+1)ai+ai+1+...≤(n−xi+1)
如果满足,最后将题目看做是在一个数轴上移动数字的问题。
答案是∑[1..n]−∑xi∗ai\sum[1..n]-\sum x_i*a_i∑[1..n]−∑xi∗ai
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
int n, m;
pii a[200010];
int main(){
//freopen("in.txt", "r", stdin);
cin >> n >> m;
for (int i = 1; i <= m; ++i) {
cin >> a[i].first;
}
for (int i = 1; i <= m; ++i) {
cin >> a[i].second;
}
sort(a + 1, a + m + 1);
ll s = 0;
for (int i = m; i >= 1; --i) {
ll len = n - a[i].first + 1;
s += a[i].second;
if (s > len)
{
printf("-1\n");
return 0;
}
}
if (s != n) {
printf("-1\n");
return 0;
}
ll ans = ll(n + 1) * n / 2;
for (int i = 1; i <= m; ++i) {
ans -= ll(a[i].first) * a[i].second;
}
printf("%lld\n", ans);
}
D - Home Garden
三个操作
1.种一棵树。此时该树的高度为0.
2.浇水h,此时所有树的高度增加h。
3.收获w,此时所有>=w的树收割。
设aia_iai是当前(i操作后)一共浇了多少水
那么i操作下的树当前的高度是acur−ai−1a_{cur}-a_{i-1}acur−ai−1
维护一个栈,用于操作2下去掉那些足够高的树
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
int q;
ll a[200020];
bool b[200020];
int idx;
queue<int> qu;
void work() {
int op;
cin >> op;
if (op == 1) {
++idx;
a[idx] = a[idx - 1];
qu.push(idx);
b[idx] = 1;
}
else if(op == 2){
++idx;
ll t;
cin >> t;
a[idx] = a[idx - 1] + t;
}
else {
++idx;
ll t;
cin >> t;
a[idx] = a[idx - 1];
int cnt = 0;
while (qu.size() && a[idx] - a[qu.front()] >= t) {
if (b[qu.front()])
cnt++;
qu.pop();
}
printf("%d\n", cnt);
}
}
int main(){
//freopen("in.txt", "r", stdin);
cin >> q;
while (q--) {
work();
}
return 0;
}
E - Sum of All Substrings
高精度加法,但是不能暴力
把一个字符串SSS代表的整数里的每个子字符串加起来,求和。
不能暴力的情况下,分不同数位上的数
手算例子:
f(379)f(379)f(379)在百位只有3
在十位有37 79 379=3+7*2
在个位有3 37 379 7 79 9 =3+7∗2+9∗3= 3+7*2+9*3=3+7∗2+9∗3
所以从高位到低位维护一个前缀和,高精度加上去就好了
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
int n;
int a[400040];
string s;
ll ts;
int main(){
//freopen("in.txt", "r", stdin);
cin >> n;
cin >> s;
for (int i = 0; i < n; ++i) {
int d = s[i] - '0';
int t = d * (i + 1);
ts += t;
int j = n - 1 - i;
ll c = 0;
ll x = ts;
while (true) {
int y = a[j] + x % 10 + c;
a[j] = y % 10;
c = y / 10;
if (a[j] == 0 && x == 0 && c == 0)
break;
j++;
x /= 10;
}
}
int m = 0;
for (int i = 400039; i >= 0; --i) {
if (a[i]) {
m = i;
break;
}
}
for (int i = m; i >= 0; --i) {
printf("%d", a[i]);
}
printf("\n");
return 0;
}
F - Buildings 2
一排楼房
给出q个查询,每个查询里面有两个下标l, r
定义当xi=maxk=[i+1..j]xkx_i=\max_{k=[i+1..j]}x_kxi=maxk=[i+1..j]xk时楼房i能被楼房j看见
也就是楼房i和楼房j之间没有更高的楼房。
问、能被lr同时看见的楼房个数。
如果单独问i看见的楼房个数,显然是求LIS最长不下降子序列
但是算两个联合起来,如果先算r看见的LIS,然后去判l和LIS的关系,不太好做。反过来,先算l看见的LIS,再看r在LIS中的位置,我们就可以很容易做出来。
G - Count Grid 3-coloring
状态压缩dp模板题。需要优化,差点就TLE了。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
ll mod = 998244353;
int n, m;
int a[201][201];
int b[202][15];
ll f[202][25000];
int p[16];
vi seq;
int sz;
vi g[25000];
int dx[25000][14];
inline int get3(int x, int pos) {
return (x % p[pos + 1]) / p[pos];
}
int main(){
//freopen("in.txt", "r", stdin);
cin >> n >> m;
p[0] = 1;
for (int i = 1; i <= 15; ++i)
p[i] = p[i - 1] * 3;
for (int i = 1; i <= n; ++i) {
char c;
for (int j = 1; j <= m; ++j) {
cin >> c;
if (c != '?') a[i][j] = c - '1';
else a[i][j] = -1;
}
}
if (n < m) {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
b[j][i - 1] = a[i][j];
}
}
swap(n, m);
}
else {
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
b[i][j - 1] = a[i][j];
}
}
}
// n > m
for (int i = 0; i < p[m]; ++i) {
bool ok = 1;
for (int j = 0; j < m - 1; ++j) {
if (get3(i, j) == get3(i, j + 1)) {
ok = 0;
break;
}
}
if (ok) seq.push_back(i);
}
sz = seq.size();
for (int i = 0; i < sz; ++i) {
for (int j = 0; j < m; ++j) {
dx[i][j] = get3(seq[i], j);
}
}
for (int i = 0; i < sz; ++i) {
for (int j = 0; j < sz; ++j) {
bool ok = 1;
for (int k = 0; k < m; ++k) {
if (dx[i][k] == dx[j][k]) {
ok = 0;
break;
}
}
if (ok) g[i].push_back(j);
}
}
f[0][0] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = 0; j < sz; ++j) {
bool ok = 1;
for (int k = 0; k < m; ++k) {
int t = get3(seq[j], k);
if (b[i][k] != -1 && t != b[i][k]) {
ok = 0;
break;
}
}
if (!ok) continue;
if (i == 1) f[i][j] = 1;
else {
for (int prej : g[j]) {
f[i][j] = (f[i][j] + f[i - 1][prej]) % mod;
}
}
}
}
ll ans = 0;
for (int j = 0; j < sz; ++j) {
ans = (ans + f[n][j]) % mod;
}
printf("%lld\n", ans);
return 0;
}