[CF] B. You Are Given a Decimal String... - Educational Codeforces Round 70 (Rated for Div. 2)

https://codeforces.com/contest/1202/problem/B

题目大意

给出一个 $0 \sim 9$ 字符组成的序列 $S \ (1 \le |S| \le 2 \times 10^6)$ 且 $S$ 总以 $0$ 开始,这个序列是由 $x, y \ (0 \le x, y \le 9)$ 由以下规则生成出来的。

  1. 最初数字 $a$ 为 $0$。输出这个数
  2. 随机的从 $x, y$ 中选出一个数加到 $a$ 上并输出 $a$ 的个位数字。重复这个过程若干次
  3. 删除生成的序列中的若干数字得到 $S$。

对于所有的 $x, y \ (0 \le x, y \le 9)$ 对,$S$ 至少删掉了某个生成序列中的多少数。如果 $x, y$ 对无法得到序列,输出 $-1$。

简要题解

序列中数字个位从 $a$ 变为 $b$,相当于我们希望知道模 $10$ 意义下 $ix + jy + a = b$ 最小的 $i + j$ 是多少。注意到 $i, j > 10$ 是没意义的。因此我们只要暴力枚举 $i, j$ 就可以得出每种 $a$ 变成 $b$ 的最小代价。

注意原串很长,所以需要把所有的转化统计出来。

复杂度

$T$:$O(n + 10^5)$

对于下面的代码,如果我们先维护所有 $diff$ 的最优值,可以省掉一个 $10$。但是这题复杂度瓶颈其实不在这里,所以无所谓了。

$S$:$O(n + 10^2)$

代码实现

#include <bits/stdc++.h>
using namespace std;

int io_=[](){ ios::sync_with_stdio(false); cin.tie(nullptr); return 0; }();

using LL = long long;
using ULL = unsigned long long;
using LD = long double;
using PII = pair<int, int>;
using VI = vector<int>;
using MII = map<int, int>;

template<typename T> void cmin(T &x,const T &y) { if(y<x) x=y; }
template<typename T> void cmax(T &x,const T &y) { if(x<y) x=y; }
template<typename T> bool ckmin(T &x,const T &y) { 
    return y<x ? (x=y, true) : false; }
template<typename T> bool ckmax(T &x,const T &y) { 
    return x<y ? (x=y, true) : false; }
template<typename T> void cmin(T &x,T &y,const T &z) {// x<=y<=z 
    if(z<x) { y=x; x=z; } else if(z<y) y=z; }
template<typename T> void cmax(T &x,T &y,const T &z) {// x>=y>=z
    if(x<z) { y=x; x=z; } else if(y<z) y=z; }

// mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
// mt19937_64 rnd_64(chrono::system_clock::now().time_since_epoch().count());

/*
---------1---------2---------3---------4---------5---------6---------7---------
1234567890123456789012345678901234567890123456789012345678901234567890123456789
*/

void solve() {
  string s; cin >> s;
  int n = s.length();

  vector<vector<int>> cnt(10, vector<int>(10));
  for (int i = 1; i < n; i++) {
    cnt[s[i - 1] - '0'][s[i] - '0']++;
  }

  vector<vector<int>> mi(10, vector<int>(10));

  for (int x = 0; x < 10; x++) {
    for (int y = 0; y < 10; y++) {
      for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
          mi[i][j] = -1;
        }
      }
      for (int i = 0; i <= 10; i++) {
        for (int j = 0; j <= 10; j++) {
          if (i + j == 0) continue;

          int diff = (i * x + j * y) % 10;

          for (int fr = 0; fr < 10; fr++) {
            int to = (fr + diff) % 10;

            if (mi[fr][to] == -1 || mi[fr][to] > i + j - 1) {
              mi[fr][to] = i + j - 1;
            }
          }
        }
      }

      int ans = 0;
      for (int i = 0; ans != -1 && i < 10; i++) {
        for (int j = 0; j < 10; j++) {
          if (!cnt[i][j]) continue;
          if (mi[i][j] == -1) {
            ans = -1;
            break;
          }

          ans += mi[i][j] * cnt[i][j];
        }
      }

      cout << ans << (" \n"[y == 9]);
    }
  }
}

int main() {
  int t = 1; 
  // cin >> t;
  while (t--) {
    solve();
  }
  return 0;
}
Prev: [CF] D. Print a 1337-string... - Educational Codeforces Round 70 (Rated for Div. 2)
Next: [LC] 3420. Count Non-Decreasing Subarrays After K Operations - Weekly Contest 432