本文主要是介绍Codeforces Round 905 (Div. 3) 补题报告,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
- 1 AC情况
- 2 题解
- A. Morning
- B. Chemistry
- C. Raspberries
- D. In Love
- E. Look Back
1 AC情况
A | B | C | D | E | F | G1 | G2 |
---|---|---|---|---|---|---|---|
Accepted \color{green}\texttt{Accepted} Accepted | Accepted \color{green}\texttt{Accepted} Accepted | Accepted \color{green}\texttt{Accepted} Accepted | Accepted \color{green}\texttt{Accepted} Accepted | Accepted \color{green}\texttt{Accepted} Accepted | - | - | - |
2 题解
A. Morning
Problem - A - Codeforces | Morning - 洛谷
题目描述
输入 t t t 组数据。
每组数据有一个四位密码。现在密码输入设备上有一个数列
1234567890
,初始时光标指向1
。在 1 1 1 秒内,你可以:
- 按下光标以显示当前数字;
- 将光标移动到任何相邻的数字。
请计算输入给定的四位密码所需的最少秒数。
题解
模拟即可,注意把0
看做10
来处理,这样从数字 i i i 移动到数字 j j j 所需的秒数就是 ∣ i − j ∣ \left|i - j\right| ∣i−j∣,最后再加上显示数字的时间 4 4 4 即可。
代码如下:
#include <bits/stdc++.h>
#define endl '\n'
#define file(FILENAME) freopen(FILENAME ".in", "r", stdin), freopen(FILENAME ".out", "w", stdout)
#define CLOSE ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
int n, t;
int main() {CLOSE;cin >> t;while (t--) {cin >> n;int a = n / 1000, b = n / 100 % 10, c = n / 10 % 10, d = n % 10; //拆分数字if (a == 0) a = 10; //10替换0if (b == 0) b = 10;if (c == 0) c = 10;if (d == 0) d = 10;int ans = 4 + abs(a - 1) + abs(b - a) + abs(c - b) + abs(d - c); //移动时间+显示时间cout << ans << endl; }return 0;
}
B. Chemistry
Problem - B - Codeforces | Chemistry - 洛谷
题目描述
输入 t t t 组数据。
每次输入 n n n 和 k k k,和一个仅包含小写字母的字符串 s s s( ∣ s ∣ = n \left|s\right| = n ∣s∣=n)。问在 s s s 中删除 k ( 0 ≤ k < n ) k(0\le k < n) k(0≤k<n) 个字符后,将 s s s 重新排列,能否构成一个回文串。
题解
回文串的特征:
- 最多只存在一个字母出现次数为奇数;
- 其余字母出现次数均为偶数。
我们可以从出现奇数次的字母入手,如果出现奇数次,删去一个,使它成为偶数;不能删了,就记录下奇数的个数。
如果最后出现奇数次的字母的个数大于 1 1 1,那么一定不是回文串。
代码如下:
#include <bits/stdc++.h>
#define endl '\n'
#define file(FILENAME) \freopen(FILENAME ".in", "r", stdin), freopen(FILENAME ".out", "w", stdout)
#define CLOSE \ios::sync_with_stdio(false); \cin.tie(0); \cout.tie(0)
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
int n, k, t, cnt[N];
char s[N];
int main() {CLOSE;cin >> t;while (t--) {memset(cnt, 0, sizeof cnt);cin >> n >> k;cin >> s;for (int i = 0; i < n; i++) //记录出现次数cnt[s[i]]++;int flag = 0;for (int i = 'a'; i <= 'z'; i++) {if (cnt[i] % 2 != 0) { //出现奇数次if (k) { //能删则删k--;cnt[i]--;} else //不能删,记录个数flag++;}}cout << (flag <= 1 ? "YES\n" : "NO\n");}return 0;
}
C. Raspberries
Problem - C - Codeforces | Raspberries - 洛谷
题目描述
输入 t t t 组数据。
每次给定数组 a 1 , a 2 , … , a n a_1,a_2,\dots,a_n a1,a2,…,an 和一个数 k ( 2 ≤ k ≤ 5 ) k(2\le k\le 5) k(2≤k≤5)。
每次操作你可以照顾到一个索引 i ( 1 ≤ i ≤ n ) i(1\le i\le n) i(1≤i≤n),令 a i = a i + 1 a_i=a_i+1 ai=ai+1。
问经过若干次操作后,能否使 ∏ i = 1 n a i m o d k = 0 \prod_{i=1}^n a_i \mod k = 0 ∏i=1naimodk=0。
题解
观察发现, k k k 的取值范围是 2 ∼ 5 2\sim 5 2∼5,除去 4 = 2 × 2 4 = 2\times 2 4=2×2 以外,其他数分解质因数都还是本身。
分类讨论:
-
k ∈ { 2 , 3 , 5 } k \in \{2,3,5\} k∈{2,3,5}:找到一个 d m i n ( a i + d i ≡ 0 ( m o d k ) ( 1 ≤ i ≤ n ) ) d_{min}(a_i+d_i\equiv 0 (\mod k)(1\le i\le n)) dmin(ai+di≡0(modk)(1≤i≤n)),也就是找到最小的一个大于 a i a_i ai 且与它最近的 k k k 的倍数与 a i a_i ai 的差,则可知 d m i n = min ( ⌈ a i k ⌉ k − a i ) d_{min}= \min\left(\lceil\frac{a_i}{k}\rceil k - a_i\right) dmin=min(⌈kai⌉k−ai)
-
k = 4 k = 4 k=4:有一下几种情况:
- 存在 a i m o d 4 = 0 ( 1 ≤ i ≤ n ) a_i\mod 4=0(1\le i\le n) aimod4=0(1≤i≤n),答案为 0 0 0
- 存在 a i m o d 2 = 0 , a j m o d 2 = 0 ( 1 ≤ i , j ≤ n , i ≠ j ) a_i\mod 2 = 0,a_j\mod 2=0(1\le i,j\le n,i\ne j) aimod2=0,ajmod2=0(1≤i,j≤n,i=j),答案为 0 0 0
- 仅存在一个 a i m o d 2 = 0 ( 1 ≤ i ≤ n ) a_i\mod 2=0(1\le i\le n) aimod2=0(1≤i≤n),再凑出一个偶数即可满足情况2,单位 1 1 1
- 存在 a i m o d 4 = 1 ( 1 ≤ i ≤ n ) a_i\mod 4=1(1\le i\le n) aimod4=1(1≤i≤n),答案为 1 1 1
- 全部是奇数,则凑出两个偶数即可满足情况2,答案为 2 2 2
分别用变量记录各自所需的 a i a_i ai 出现的次数即可,注意判断顺序,答案小的优先。
代码如下:
#include <bits/stdc++.h>
#define endl '\n'
#define file(FILENAME) \freopen(FILENAME ".in", "r", stdin), freopen(FILENAME ".out", "w", stdout)
#define CLOSE \ios::sync_with_stdio(false); \cin.tie(0); \cout.tie(0)
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
int t, n, k, a;
int main() {CLOSE;cin >> t;while (t--) {cin >> n >> k;int ans = 0, p1 = 0, p2 = 0, p3 = 0, p4 = 0;for (int i = 1; i <= n; i++) {cin >> a;if (k != 4) ans = min(ans, (a / k + (a % k != 0)) * k - a); //k不是4,找d的最小值else { //k = 4if (a % 4 == 0) p1++; //记录情况1else if (a % 2 == 0) p2++; //记录情况2、3else if ((a + 1) % 4 == 0) p3++; //记录情况4else p4++; //记录情况5}}if (k != 4) cout << ans << endl;else {if (p1 > 0) cout << 0 << endl; //判断情况1else if (p2 >= 2) cout << 0 << endl; //判断情况2else if (p2 == 1) cout << 1 << endl; //判断情况3else if (p3 > 0) cout << 1 << endl; //判断情况4else cout << 2 << endl; //判断情况5}}return 0;
}
D. In Love
Problem - D - Codeforces | In Love - 洛谷
题意描述
现在给出 q q q 次操作:
- + l r +\ l\ r + l r:在不去重集合中加入片段 ( l , r ) (l, r) (l,r)
- − l r -\ l\ r − l r:在不去重集合中删除一个片段 ( l , r ) (l, r) (l,r)
每次操作后,判断集合中是否存在一对片段不重合。
题解
我们只需要判断相隔最小的两个片段是否重合即可。如果不重合,则至少存在一对;如果重合,那么其他的片段也必然重合。
而一对不重合的片段 ( l 1 , r 1 ) (l_1,r_1) (l1,r1) 和 ( l 2 , r 2 ) (l_2, r_2) (l2,r2) 满足 r 1 < l 1 r_1<l_1 r1<l1。
所以,我们可以分开存储左端点 l l l 和右端点 r r r。如果 r m i n < l m a x r_{min}<l_{max} rmin<lmax ,则存在;反之,不存在。
能够快速排序和删除,还要满足不去重的特性,multiset
是最佳的选择。
注意, l l l 每次取最大值,而multiset
默认升序排序,但我们知道, ∀ a < b < 0 , − a > − b \forall a<b<0,-a>-b ∀a<b<0,−a>−b,可以保存 − l -l −l 的值,删除使用时取相反数即可。
代码如下:
#include <bits/stdc++.h>
#define endl '\n'
#define file(FILENAME) \freopen(FILENAME ".in", "r", stdin), freopen(FILENAME ".out", "w", stdout)
#define CLOSE \ios::sync_with_stdio(false); \cin.tie(0); \cout.tie(0)
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
int n, l, r;
map<int, int> visl, visr;
char k;
multiset<int> L, R;
int main() {CLOSE;cin >> n;for (int i = 1; i <= n; i++) {cin >> k >> l >> r;if (k == '+') {L.insert(-l);visl[l]++;R.insert(r);visr[r]++;} else {int t = L.erase(-l);t = R.erase(r);visl[l]--, visr[r]--;if (visl[l]) L.insert(-l);if (visr[r]) R.insert(r);}cout << (-(*L.begin()) > *R.begin() ? "YES\n" : "NO\n");}return 0;
}
E. Look Back
Problem - E - Codeforces | Look Back - 洛谷
题目描述
输入 t t t 组数据。
给定一个数组 a 1 , a 2 , … , a n a_1,a_2,\dots,a_n a1,a2,…,an。
可进行操作:找到一个索引 i ( 1 ≤ i ≤ n ) i(1\le i\le n) i(1≤i≤n),令 a i = a i × 2 a_i = a_i\times 2 ai=ai×2。
问最少进行多少次操作,能使数组成为一个非递减数组。
题解
L o g i Log_i Logi :表示 a i a_i ai 需要乘上 2 i 2^i 2i(即需要操作 i i i 次), L o g i ∈ N Log_i\in \N Logi∈N。
从左往右对 a i ( 1 ≤ i ≤ n ) a_i(1\le i\le n) ai(1≤i≤n) 操作。
先令 L o g i = L o g i − 1 ( 2 ≤ i ≤ n ) Log_i=Log_{i-1}(2\le i\le n) Logi=Logi−1(2≤i≤n)。
分类讨论:
-
a i > a i − 1 a_i>a_{i - 1} ai>ai−1:说明 L o g i Log_i Logi 过大, 要让操作次数尽可能小且仍要满足条件,则设 L o g i Log_i Logi 要减去 k ( k ∈ N ) k(k\in \N) k(k∈N)
a i ≥ a i − 1 × 2 k 2 k ≥ a i a i − 1 log 2 ( 2 k ) ≥ log 2 ( a i a i − 1 ) k ≥ log 2 ( a i a i − 1 ) ∵ k ∈ N , a i × 2 L o g i − 1 − k ≥ a i − 1 , ∴ k = ⌊ log 2 ( a i a i − 1 ) ⌋ \begin{aligned} a_i&\ge a_{i - 1}\times 2^{k} \\ 2^{k}&\ge \frac{a_{i}}{a_{i-1}} \\ \log_2\left(2^{k}\right)&\ge \log_2\left(\frac{a_{i}}{a_{i-1}}\right) \\ k&\ge \log_2\left(\frac{a_{i}}{a_{i-1}}\right) \\ \because k\in \N,a_i\times 2^{Log_{i - 1}-k}\ge a_{i - 1},\\ \therefore k&= \left\lfloor\log_2\left(\frac{a_{i}}{a_{i-1}}\right)\right\rfloor \end{aligned} ai2klog2(2k)k∵k∈N,ai×2Logi−1−k≥ai−1,∴k≥ai−1×2k≥ai−1ai≥log2(ai−1ai)≥log2(ai−1ai)=⌊log2(ai−1ai)⌋
注意, L o g i Log_i Logi 不能为负数,所以应是
L o g i = max ( 0 , L o g i − 1 − ⌊ log 2 ( a i a i − 1 ) ⌋ ) Log_i=\max\left(0,Log_{i-1}-\left\lfloor\log_2\left(\frac{a_{i}}{a_{i-1}}\right)\right\rfloor\right) Logi=max(0,Logi−1−⌊log2(ai−1ai)⌋) -
a i < a i − 1 a_i<a_i-1 ai<ai−1:同理,设 L o g i Log_i Logi 要加上 k ( k ∈ N ) k(k\in \N) k(k∈N)
a i × 2 k ≥ a i − 1 2 k ≥ a i − 1 a i log 2 ( 2 k ) ≥ log 2 ( a i − 1 a i ) k ≥ log 2 ( a i − 1 a i ) ∵ k ∈ N , a i × 2 L o g i − 1 + k ≥ a i − 1 , ∴ k = ⌈ log 2 ( a i − 1 a i ) ⌉ \begin{aligned} a_i \times 2^{k} &\ge a_{i - 1} \\ 2^{k}&\ge \frac{a_{i - 1}}{a_{i}} \\ \log_2\left(2^{k}\right)&\ge \log_2\left(\frac{a_{i-1}}{a_{i}}\right) \\ k&\ge \log_2\left(\frac{a_{i-1}}{a_{i}}\right) \\ \because k\in \N,a_i\times 2^{Log_{i - 1}+k}\ge a_{i - 1},\\ \therefore k&= \left\lceil\log_2\left(\frac{a_{i-1}}{a_{i}}\right)\right\rceil \end{aligned} ai×2k2klog2(2k)k∵k∈N,ai×2Logi−1+k≥ai−1,∴k≥ai−1≥aiai−1≥log2(aiai−1)≥log2(aiai−1)=⌈log2(aiai−1)⌉
由此可得
L o g i = max ( 0 , L o g i − 1 + ⌈ log 2 ( a i − 1 a i ) ⌉ ) Log_i=\max\left(0,Log_{i-1}+\left\lceil\log_2\left(\frac{a_{i-1}}{a_{i}}\right)\right\rceil\right) Logi=max(0,Logi−1+⌈log2(aiai−1)⌉)
∑ i = 1 n L o g i \sum_{i=1}^nLog_i ∑i=1nLogi 就是操作总次数。
代码如下:
#include <bits/stdc++.h>
#define endl '\n'
#define file(FILENAME) \freopen(FILENAME ".in", "r", stdin), freopen(FILENAME ".out", "w", stdout)
#define CLOSE \ios::sync_with_stdio(false); \cin.tie(0); \cout.tie(0)
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
int t, n;
ll a[N], Log[N];
int main() {CLOSE;cin >> t;while (t--) {cin >> n;ll ans = 0;for (int i = 1; i <= n; i++) {cin >> a[i];if (i > 1) {if (a[i] > a[i - 1])Log[i] =max((ll)0, Log[i - 1] -(ll)floor(log2(a[i] * 1.0 / a[i - 1])));elseLog[i] =max((ll)0,Log[i - 1] + (ll)ceil(log2(a[i - 1] * 1.0 / a[i])));ans += Log[i];}}cout << ans << endl;}return 0;
}
这篇关于Codeforces Round 905 (Div. 3) 补题报告的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!