AtCoder Beginner Contest 378 考试总结
发挥还行,就是罚时吃饱了,B 题卡精度卡成 78 了。
赛时得分:
A | B | C | D | E | F | G |
---|---|---|---|---|---|---|
√ | √ | √ | √ | √ | × | × |
[ABC378A] Pairing
先对序列排个序,然后从小往大扫,如果和之后匹配了就贡献加一,然后跳过一个位置继续匹配。
时间复杂度 \(O(4)\)。
#include<bits/stdc++.h>
#define ll long long
#define For(i,l,r) for(int i=l;i<=r;++i)
#define FOR(i,r,l) for(int i=r;i>=l;--i)
using namespace std;
const int N = 5;
int a[N], ans;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
For(i,1,4) cin >> a[i];
sort(a + 1, a + 5);
For(i,1,4) {
if(a[i] == a[i+1]) ans++, i++;
}
cout << ans << '\n';
return 0;
}
[ABC378B] Garbage Collection
数学题,答案就是:
- 若 \(d\le r_t\),则 \(r_t\);
- 若 \(d>r_t\),则 \(\left \lceil \dfrac{d-r_t}{q_t} \right \rceil q_t + r_t\);
#include<bits/stdc++.h>
#define int long long
#define For(i,l,r) for(int i=l;i<=r;++i)
#define FOR(i,r,l) for(int i=r;i>=l;--i)
using namespace std;
const int N = 1e5 + 10;
struct Node {
int q, r;
} a[N];
int n, Q;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
For(i,1,n) cin >> a[i].q >> a[i].r;
cin >> Q;
while(Q--) {
int t, d;
cin >> t >> d;
if(d <= a[t].r) {
cout << a[t].r << '\n';
continue;
}
cout << ((d-a[t].r-1) / a[t].q + 1) * a[t].q + a[t].r << '\n';
}
return 0;
}
[ABC378C] Repeating
用 \(last_i\) 数组记录上一次 \(a_i\) 出现的位置,每次动态更新,动态输出即可。
发现值域到达 \(10^9\),直接无脑丢进 map
完事。
时间复杂度 \(O(n\log n)\)。
#include<bits/stdc++.h>
#define ll long long
#define For(i,l,r) for(int i=l;i<=r;++i)
#define FOR(i,r,l) for(int i=r;i>=l;--i)
using namespace std;
const int N = 2e5 + 10;
int n, a[N];
map<int, int> last;
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
For(i,1,n) cin >> a[i];
For(i,1,n) {
if(!last[a[i]]) {
cout << "-1 ";
} else cout << last[a[i]] << ' ';
last[a[i]] = i;
}
return 0;
}
[ABC378D] Count Simple Paths
发现 \(n\le10\),直接暴搜。
不能走重复路径,用标记记录什么地方走过了,下次不能再走。
然后对于每一个 \((i,j)\) 暴力搜索长度为 \(k\) 的路径数量即可。
#include<bits/stdc++.h>
#define int long long
#define For(i,l,r) for(int i=l;i<=r;++i)
#define FOR(i,r,l) for(int i=r;i>=l;--i)
using namespace std;
const int N = 15;
const int dx[] = {0, 0, 1, -1};
const int dy[] = {1, -1, 0, 0};
int n, m, k, ans;
char a[N][N];
bool vis[N][N];
void dfs(int x, int y, int len) {
if(len == k) {
ans++;
return ;
}
For(i,0,3) {
int nx = x + dx[i], ny = y + dy[i];
if(nx >= 1 && nx <= n && ny >= 1 && ny <= m && !vis[nx][ny] && a[nx][ny] == '.') {
vis[x][y] = 1;
dfs(nx, ny, len + 1);
vis[x][y] = 0;
}
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n >> m >> k;
For(i,1,n) {
For(j,1,m) {
cin >> a[i][j];
}
}
For(i,1,n) {
For(j,1,m) {
if(a[i][j] == '.') {
memset(vis, 0, sizeof vis);
dfs(i, j, 0);
}
}
}
cout << ans << '\n';
return 0;
}
[ABC378E] Mod Sigma Problem
发现可以拆贡献的方式:
\[\sum\limits_{l=1}^n \sum\limits_{r=l}^n (\sum\limits_{l\le k\le r} a_k) \bmod m
\]
然后算出 \(a_i\) 的前缀和 \(sum_i\)。
\[\begin{aligned}
&\sum\limits_{l=1}^n \sum\limits_{r=l}^n (sum_r-sum_{l-1}) \bmod m\\
&\sum\limits_{l=1}^n \sum\limits_{r=l}^n (sum_r\bmod m-sum_{l-1}\bmod m+[sum_r < sum_{l-1}] \times m)
&
\end{aligned}
\]
然后就很简单了,记录 \(sum_i \bmod m\) 的后缀和 \(s_i\),记录 \(b_i\) 为所有 \(>sum_{i-1}\) 的 \(sum_j(j\ge i)\) 的个数。
前者 \(O(n)\) 扫一遍,后者用树状数组 \(O(n\log n)\) 统计即可。
最后答案为:\(\sum\limits_{i=1}^n s_i - (n-i+1)\times (sum_{i-1}\bmod m)+b_{i-1}\times m\)。
总时间复杂度 \(O(n\log n)\)。
#include<bits/stdc++.h>
#define int long long
#define For(i,l,r) for(int i=l;i<=r;++i)
#define FOR(i,r,l) for(int i=r;i>=l;--i)
using namespace std;
const int N = 1e6 + 10;
int n, m, a[N], sum[N], s[N], ans, b[N], t[N];
int lb(int x) {
return x & -x;
}
int qry(int x) {
if(x <= 0) return 0;
int res = 0;
for (int i = x; i; i -= lb(i)) {
res += t[i];
}
return res;
}
void add(int x, int k) {
for (int i = x; i <= 2e5; i += lb(i)) {
t[i] += k;
}
return ;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n >> m;
For(i,1,n) cin >> a[i], sum[i] = sum[i-1] + a[i];
FOR(i,n,1) {
add(sum[i] % m + 1, 1);
b[i-1] = qry((sum[i-1] % m));
}
FOR(i,n,1) {
s[i] = s[i+1] + sum[i] % m;
}
For(i,1,n) {
int len = n - i + 1;
ans += (s[i] - len * (sum[i-1] % m) + b[i-1] * m);
}
cout << ans << '\n';
return 0;
}