比赛链接:Here

ABC水题,

D - Multiple of 2019 (DP + 分析)

题意:

给定数字串S,计算有多少个子串 AtCoder Beginner Contest 164 - 图1 ,满足 AtCoder Beginner Contest 164 - 图2AtCoder Beginner Contest 164 - 图3 的倍数

思路:

AtCoder Beginner Contest 164 - 图4

而且 AtCoder Beginner Contest 164 - 图5#card=math&code=s%5Bl%2C%20r%5D%20%2A%2010%5E%7Bn-r%7D%20%3D%20s%5Bl%2Cr%5D%5C%252019%2A%2810%5E%7Bn-r%7D%5C%252019%29)

因为 AtCoder Beginner Contest 164 - 图6 (因为 AtCoder Beginner Contest 164 - 图7 没有质因子 AtCoder Beginner Contest 164 - 图8AtCoder Beginner Contest 164 - 图9

因此只有当 AtCoder Beginner Contest 164 - 图10 时,式子左边 AtCoder Beginner Contest 164 - 图11 ,这意味着 AtCoder Beginner Contest 164 - 图12 没有影响,

那么直接计算 AtCoder Beginner Contest 164 - 图13 的数量即可,

因为这种情况下一定是 AtCoder Beginner Contest 164 - 图14

  1. int a[2040] = {1};
  2. int main() {
  3. cin.tie(nullptr)->sync_with_stdio(false);
  4. string s; cin >> s;
  5. int ans = 0, t = 1, cnt = 0;
  6. for (int i = s.size() - 1; ~i; i--) {
  7. cnt = (cnt + t * (s[i] - '0')) % 2019;
  8. ans += a[cnt]++;
  9. t = (t * 10) % 2019;
  10. }
  11. cout << ans;
  12. }

E Two Currencies (最短路,Good)

题意:

给定 AtCoder Beginner Contest 164 - 图15 个点,AtCoder Beginner Contest 164 - 图16 条无向边,初始状态下手里有 AtCoder Beginner Contest 164 - 图17 个银币。从 AtCoder Beginner Contest 164 - 图18 点到 AtCoder Beginner Contest 164 - 图19 点需要花费 AtCoder Beginner Contest 164 - 图20 个硬币,AtCoder Beginner Contest 164 - 图21 个时间单位。在每个点可以花 AtCoder Beginner Contest 164 - 图22 个时间单位兑换 AtCoder Beginner Contest 164 - 图23 个银币,求从起点 AtCoder Beginner Contest 164 - 图24 到各个点需要的最短时间。

思路:
这题很关键的一个突破口是数据范围:AtCoder Beginner Contest 164 - 图25 个点,从 AtCoder Beginner Contest 164 - 图26AtCoder Beginner Contest 164 - 图27 花费不超过 AtCoder Beginner Contest 164 - 图28 银币,所以总花费不超过AtCoder Beginner Contest 164 - 图29 .通过一个二维数组 AtCoder Beginner Contest 164 - 图30 来表示到达 AtCoder Beginner Contest 164 - 图31 点时还剩下 AtCoder Beginner Contest 164 - 图32 个银币时需要的时间最小值,然后跑一遍最短路,最后遍历一遍就可以输出最小值。

注意银币最大只需要 AtCoder Beginner Contest 164 - 图33 ,所以输入 AtCoder Beginner Contest 164 - 图34 的时候记得判断

  1. struct E {ll to, co, ti;};
  2. struct P {ll ti, id, re;};
  3. bool operator <(const P &a, const P &b) {return a.ti > b.ti;}
  4. ll f[50][5001], c[50], d[50], ans[50];
  5. vector<E>e[50];
  6. priority_queue<P> que;
  7. int main() {
  8. cin.tie(nullptr)->sync_with_stdio(false);
  9. int n, m, s;
  10. cin >> n >> m >> s;
  11. while (m--) {
  12. ll u, v, a, b;
  13. cin >> u >> v >> a >> b;
  14. u--, v--;
  15. e[u].push_back({v, a, b});
  16. e[v].push_back({u, a, b});
  17. }
  18. for (int i = 0; i < n; ++i) cin >> c[i] >> d[i];
  19. que.push({1, 0, min(s * 1ll, 2500ll)});
  20. while (que.size()) {
  21. P p = que.top(); que.pop();
  22. if (f[p.id][p.re])continue;
  23. f[p.id][p.re] = p.ti;
  24. if (!ans[p.id])ans[p.id] = p.ti;
  25. for (E q : e[p.id])
  26. if (p.re >= q.co && !f[q.to][p.re - q.co])
  27. que.push({p.ti + q.ti, q.to, p.re - q.co});
  28. if (p.re + c[p.id] <= 2500)
  29. que.push({p.ti + d[p.id], p.id, p.re + c[p.id]});
  30. }
  31. for (int i = 1; i < n; ++i) cout << --ans[i] << "\n";
  32. }