Loading

AtCoder Beginner Contest 378 考试总结

发挥还行,就是罚时吃饱了,B 题卡精度卡成 78 了。

image

赛时得分:

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;
}
posted @ 2024-11-04 11:37  Daniel_yzy  阅读(52)  评论(0编辑  收藏  举报