QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#557023#2835. Number Theoryucup-team1198WA 952ms29920kbC++205.4kb2024-09-11 00:11:352024-09-11 00:11:35

Judging History

你现在查看的是最新测评结果

  • [2024-09-11 00:11:35]
  • 评测
  • 测评结果:WA
  • 用时:952ms
  • 内存:29920kb
  • [2024-09-11 00:11:35]
  • 提交

answer

#include <map>
#include <set>
#include <array>
#include <cmath>
#include <deque>
#include <bitset>
#include <random>
#include <string>
#include <vector>
#include <cassert>
#include <complex>
#include <iomanip>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>

using namespace std;

const int INF = 1e9;

const int MAXN = 5e3 + 100;
const int MAXD = 30;
int pre_dp[2][2 * 6 * MAXN][2 * MAXD + 1];

int dp[2][2 * 6 * MAXN][3];

int lst(int x) {
  int res = x % 10;
  if (res < 0) res += 10;
  return res;
}

int rest(int x) {
  return (x - lst(x)) / 10;
}

int rest9(int x) {
  int r = x % 9;
  if (r < 0) r += 9;
  return (x - r) / 9;
}

int solve(string ns) {
  reverse(ns.begin(), ns.end());
  ns.push_back('0');
  ns.push_back('0');
  ns.push_back('0');
  vector<int> n;
  for (char ch : ns) {
    n.push_back(ch - '0');
  }
  int l = n.size();
  int maxc = 5 * l + 30;
  int maxd = (maxc + 89) / 90;

  for (int i = 0; i <= 1; ++i) {
    for (int j = -maxc; j <= maxc; ++j) {
      fill(dp[i][j + maxc], dp[i][j + maxc] + 2 * MAXD + 1, INF);
    }
  }
  for (int c = -maxc; c <= maxc; ++c) {
    fill(pre_dp[0][c + maxc], pre_dp[0][c + maxc] + 2 * MAXD + 1, INF);
  }

  for (int c = -maxc; c <= maxc; ++c) {
    if (lst(c) != n[0])
      continue;
    int carry = rest(c);
    int val = 0;
    int rem = lst(n[1] - carry);
    int start = rest(c - rem) * 10 + rem;
    for (int c1 = start; c1 <= c + 6; c1 += 10) {
      int val1 = val + abs(c - c1);
      int carry1 = rest(carry + c1);
      int delta1 = carry1 - rest9(c1);
      //cerr << "to " << 2 << ' ' << c1 << ' ' << delta1 << ' ' << val1 << '\n';
      pre_dp[0][maxc + c1][MAXD + delta1] = min(pre_dp[0][maxc + c1][MAXD + delta1], val1);
    }
  }
  maxd = (maxd + 10) / 10;
  for (int i = 2; i < 4; ++i) {
    for (int c = -maxc; c <= maxc; ++c) {
      fill(pre_dp[(i + 1) % 2][c + maxc] + MAXD - maxd - 1, pre_dp[(i + 1) % 2][c + maxc] + MAXD + maxd + 1, INF);
    }
    int cur_maxc = (l - i) * 5 + 10;
    for (int c = -cur_maxc; c <= cur_maxc; ++c) {
      for (int delta = -maxd; delta <= maxd; ++delta) {
        int val = pre_dp[i % 2][c + maxc][delta + MAXD];
        if (val == INF) continue;
        //cerr << i << ' ' << c << ' ' << delta << ' ' << val << '\n';
        int carry = rest9(c) + delta;
        int rem = lst(n[i] - carry);
        int start = rest(c - rem) * 10 + rem;
        for (int c1 = start; c1 <= c + 6; c1 += 10) {
          int val1 = val + i * abs(c - c1);
          int carry1 = rest(carry + c1);
          int delta1 = carry1 - rest9(c1);
          
          //cerr << " to " << i + 1 << ' ' << c1 << ' ' << delta1 << ' ' << val1 << '\n';

          pre_dp[(i + 1) % 2][maxc + c1][MAXD + delta1] = min(pre_dp[(i + 1) % 2][maxc + c1][MAXD + delta1], val1);
        }
      }
    }
    maxd = (maxd + 10) / 10;
  }
  for (int c = -maxc; c <= maxc; ++c) {
    for (int d = -1; d <= 1; ++d)
      dp[4 & 1][c + maxc][1 + d] = pre_dp[4 & 1][c + maxc][MAXD + d];
  }
  for (int i = 4; i < l; ++i) {
    int cur_maxc = (l - i) * 5 + 10;
    for (int c = -cur_maxc; c <= cur_maxc; ++c) {
      fill(dp[(i + 1) % 2][c + maxc], dp[(i + 1) % 2][c + maxc] + 3, INF);
    }
    for (int c = -cur_maxc; c <= cur_maxc; ++c) {
      for (int delta = -maxd; delta <= maxd; ++delta) {
        int val = dp[i % 2][c + maxc][delta + 1];
        if (val == INF) continue;
        //cerr << i << ' ' << c << ' ' << delta << ' ' << val << '\n';

        int carry = rest9(c) + delta;
        int rem = lst(n[i] - carry);
        int start = rest(c - rem) * 10 + rem;

        for (int c1 = start; c1 <= c + 6; c1 += 10) {
          int val1 = val + i * abs(c - c1);
          int carry1 = rest(carry + c1);
          int delta1 = carry1 - rest9(c1);

          //cerr << " to " << i + 1 << ' ' << c1 << ' ' << delta1 << ' ' << val1 << '\n';

          dp[(i + 1) % 2][maxc + c1][1 + delta1] = min(dp[(i + 1) % 2][maxc + c1][1 + delta1], val1);
        }
      }
    }
  }
  int ans = INF;
  for (int i = -maxc; i <= maxc; ++i) {
    for (int delta = -1; delta <= 1; ++delta) {
      int carry = rest9(i) + delta;
      if (carry == 0) {
        ans = min(ans, dp[l % 2][i + maxc][1 + delta]);
      }
    }
  }
  return ans;
}

//#define STRESS
#define RANDOM

#ifdef STRESS

const int LEN = 7;
const int K = 500000;
int precalc[K];

void gen(int i, int cur, int cost, int num) {
  if (i == LEN) {
    if (0 < cur && cur < K) {
      precalc[cur] = min(precalc[cur], cost);
    }

    return;
  }
  for (int j = -7; j <= 7; ++j) {
    gen(i + 1, cur + j * num, cost + abs(j) * i, num * 10 + 1);
  }
}

int dumb(string n) {
  int x = stoi(n);
  return precalc[x];
}

#endif

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);

#if defined(STRESS)
  fill(precalc, precalc + K, INF);
  gen(1, 0, 0, 1);
  for (int n = 1; n < K; ++n) {
    string ns = to_string(n);
    int ans1 = solve(ns);
    int ans2 = dumb(ns);
    if (ans1 != ans2) {
      cerr << "BUG!!\n";
      cerr << ns << '\n';
      cerr << "wrong: " << ans1 << " right: " << ans2 << "\n\n\n";
      break;
    }
  }
#elif defined(RANDOM)
  const int L = 5000;
  string n;
  for (int i = 0; i < L; ++i)
    n += char('0' + rand() % 10);
  cout << solve(n) << '\n';
#else
  string n;
  while (cin >> n) {
    cout << solve(n) << '\n';
  }
#endif
  return 0;
}

详细

Test #1:

score: 0
Wrong Answer
time: 952ms
memory: 29920kb

input:

12
100
998244353

output:

30950849

result:

wrong answer 1st lines differ - expected: '3', found: '30950849'