360-temp
A - A Healthy Breakfast
判断 R
是否在 M
的左边
void solve() {
string s;cin >> s;
auto it1 = s.find('R');
auto it2 = s.find('M');
if (it1 < it2) {
cout << "Yes\n";
} else {
cout << "No\n";
}
}
B - Vertical Reading
给你两个由小写英文字母组成的字符串
请判断是否存在一对整数
- 如果从开头开始每隔
个字符拆分 ,那么长度至少为 的子串的 个字符依次连接等于 。
模拟即可。
void solve() {
string s, t;cin >> s >> t;
for (int c = 1;c < s.size();c++) {
for (int w = c;w < s.size();w++) {
vector<string> st;
for (int i = 0;i < s.size();i += w) {
st.push_back(s.substr(i, w));
}
string ss = "";
for (auto x : st) {
if (x.size() >= c) {
ss += x[c - 1];
}
}
if (ss == t) {
cout << "Yes\n";return;
}
}
}
cout << "No\n";
}
C - Move It
有
您可以重复执行选择物品并将其移动到另一个盒子中的操作 0 次或更多次。如果被移动物品的重量为
求使每个箱子正好装一件物品所需的最小总成本。
void solve() {
int n;cin >> n;
vector<int> a(n + 1), w(n + 1);
map<int, vector<int>>mp;
for (int i = 1;i <= n;i++)cin >> a[i];
for (int i = 1;i <= n;i++) {
int w;cin >> w;
mp[a[i]].push_back(w);
}
int ans = 0;
for (auto [x, y] : mp) {
ans += accumulate(y.begin(), y.end(), 0) - *max_element(y.begin(), y.end());
}
cout << ans << '\n';
}
D - Ghost Ants
在标有
假设当前时间为
求
无想法
Solution
双指针/二分
没有想到,这段时间的状态太差了,加上 zys 根本不训练,真的恶心,一想到之后队友又不训练,我是真 tm 想退役了。加训吧
注意题目中的正方向和负方向
当向右时,比它还左边的肯定要去掉,再加上到右边恰好彼此之差没有超过时间的位置,还是很好判断的
时间复杂度:
#define int long long
void solve() {
int n, t;cin >> n >> t;
string s;cin >> s;
vector<int> x1, x2;
for (int i = 0;i < n;i++) {
int a;cin >> a;
if (s[i] == '1') {
x1.push_back(a);
} else {
x2.push_back(a);
}
}
sort(x1.begin(), x1.end());
sort(x2.begin(), x2.end());
int l = 0, r = 0;
int ans = 0;
for (int i = 0;i < x1.size();i++) {
while (l < x2.size() && x2[l] < x1[i])l++;
while (r < x2.size() && x2[r] <= x1[i] + 2 * t)r++;
ans += r - l;
}
cout << ans << '\n';
}
E - Random Swaps of Balls
有
高桥将执行下面的操作
- 在
之间均匀随机地选择一个整数两次。设 和 为所选整数。如果是 ,把左边的 和 交换。
经过
Solution
组合数学/ 概率DP
设
若知道了
这时
只需求出
每次操作都有:
即在第
状态转移方程:
计算出的
千万要注意 mod 的各种情况,防止犯低级错误!
void solve() {
int n, k;cin >> n >> k;
int p = (n * n - 2 * (n - 1)) % mod * inv(n * n % mod) % mod;
int q = 2 * inv(n * n % mod) % mod;
vector<int> f(k + 1);
f[0] = 1;
for (int i = 1;i <= k;i++) {
f[i] = (f[i - 1] * p % mod + (1 - f[i - 1] + mod) * q % mod) % mod;
}
cout << (2 + n * (1 - f[k] + mod) % mod) % mod * inv(2) % mod << '\n';
}
更加容易理解的方式:
与上面的思想相同都是想办法计算出
易得:在没有进行操作的时候
若经过操作在位置 1,则有两种可能:
- 本来就在位置 1,位置没有变化
- 本来不在位置 1,位置交换到了位置 1
若经过操作不在位置 1,则有两种可能:
- 本来在位置 1,位置发生了改变
- 本来不在位置 1,位置随意,只要不交换到位置 1 即可
void solve() {
int n, k;cin >> n >> k;
int p = (n * n - 2 * (n - 1)) % mod * inv(n * n % mod) % mod;
int q = 2 * inv(n * n % mod) % mod;
vector<array<int, 2>> f(k + 1);//f[i][0/1]代表经过i次操作后在/不在位置1
f[0][0] = 1;
for (int i = 1;i <= k;i++) {
f[i][0] = f[i - 1][0] * p % mod + f[i - 1][1] * q % mod;
f[i][0] %= mod;
f[i][1] = f[i - 1][0] * (1 - p + mod) % mod + f[i - 1][1] * (1 - q + mod) % mod;
f[i][1] %= mod;
}
cout << (2 + n * (1 - f[k][0] + mod) % mod) % mod * inv(2) % mod << '\n';
}
G - Suitable Edit for LIS
给你一个长度为
- 选定一个
,给 赋任意值。
求操作后
Solution
做这个题目的前提条件: ABC354F - Useless for LIS
比较麻烦,先放着,挖坑...