QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#184982#4904. 圆滚滚的算术占卜hos_lyric#5 171ms194980kbC++149.1kb2023-09-21 15:19:262024-07-04 02:06:14

Judging History

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

  • [2024-07-04 02:06:14]
  • 评测
  • 测评结果:5
  • 用时:171ms
  • 内存:194980kb
  • [2023-09-21 15:19:26]
  • 提交

answer

#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

using namespace std;

using Int = long long;

template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")

////////////////////////////////////////////////////////////////////////////////
template <unsigned M_> struct ModInt {
  static constexpr unsigned M = M_;
  unsigned x;
  constexpr ModInt() : x(0U) {}
  constexpr ModInt(unsigned x_) : x(x_ % M) {}
  constexpr ModInt(unsigned long long x_) : x(x_ % M) {}
  constexpr ModInt(int x_) : x(((x_ %= static_cast<int>(M)) < 0) ? (x_ + static_cast<int>(M)) : x_) {}
  constexpr ModInt(long long x_) : x(((x_ %= static_cast<long long>(M)) < 0) ? (x_ + static_cast<long long>(M)) : x_) {}
  ModInt &operator+=(const ModInt &a) { x = ((x += a.x) >= M) ? (x - M) : x; return *this; }
  ModInt &operator-=(const ModInt &a) { x = ((x -= a.x) >= M) ? (x + M) : x; return *this; }
  ModInt &operator*=(const ModInt &a) { x = (static_cast<unsigned long long>(x) * a.x) % M; return *this; }
  ModInt &operator/=(const ModInt &a) { return (*this *= a.inv()); }
  ModInt pow(long long e) const {
    if (e < 0) return inv().pow(-e);
    ModInt a = *this, b = 1U; for (; e; e >>= 1) { if (e & 1) b *= a; a *= a; } return b;
  }
  ModInt inv() const {
    unsigned a = M, b = x; int y = 0, z = 1;
    for (; b; ) { const unsigned q = a / b; const unsigned c = a - q * b; a = b; b = c; const int w = y - static_cast<int>(q) * z; y = z; z = w; }
    assert(a == 1U); return ModInt(y);
  }
  ModInt operator+() const { return *this; }
  ModInt operator-() const { ModInt a; a.x = x ? (M - x) : 0U; return a; }
  ModInt operator+(const ModInt &a) const { return (ModInt(*this) += a); }
  ModInt operator-(const ModInt &a) const { return (ModInt(*this) -= a); }
  ModInt operator*(const ModInt &a) const { return (ModInt(*this) *= a); }
  ModInt operator/(const ModInt &a) const { return (ModInt(*this) /= a); }
  template <class T> friend ModInt operator+(T a, const ModInt &b) { return (ModInt(a) += b); }
  template <class T> friend ModInt operator-(T a, const ModInt &b) { return (ModInt(a) -= b); }
  template <class T> friend ModInt operator*(T a, const ModInt &b) { return (ModInt(a) *= b); }
  template <class T> friend ModInt operator/(T a, const ModInt &b) { return (ModInt(a) /= b); }
  explicit operator bool() const { return x; }
  bool operator==(const ModInt &a) const { return (x == a.x); }
  bool operator!=(const ModInt &a) const { return (x != a.x); }
  friend std::ostream &operator<<(std::ostream &os, const ModInt &a) { return os << a.x; }
};
////////////////////////////////////////////////////////////////////////////////

constexpr unsigned MO = 998244353;
using Mint = ModInt<MO>;


constexpr int E = 18;

Int ten[E + 1];

constexpr int LIM_BRUTE = 260'000;
pair<Mint, Mint> brt[LIM_BRUTE + 1];
Mint brtSum[LIM_BRUTE + 1];

/*
  start: len(hi) = f, S(hi) = a, lo = 10^e - b
  score: x -> p x + q hi + r
  goal: --hi, lo = 10^e - c
*/
struct Result {
  Mint p, q, r;
  int c;
  void mul(Mint val) {
    p *= val;
    q *= val;
    r *= val;
  }
  friend ostream &operator<<(ostream &os, const Result &r) {
    return os << "(" << r.p << "," << r.q << "," << r.r << "; " << r.c << ")";
  }
};
Result small[E][9 * E + 1][1000];
Result dp[E + 1][E][9 * E + 1][9 * E + 1];

// 0 -> []
vector<int> toDigits(Int s) {
  vector<int> digits;
  for (; s; s /= 10) {
    digits.push_back(s % 10);
  }
  return digits;
}

Mint solve(Int s) {
  Mint score = 0;
  if (s == ten[E]) {
    score = s;
    --s;
  }
  if (s < ten[3]) {
    const Result &res = small[0][0][s];
    score *= res.p;
    score += res.r;
    assert(!res.c);
    return score;
  }
  {
    const auto digits = toDigits(s);
    const int len = digits.size();
    assert(3 < len); assert(len <= E);
    int a = 0;
    for (int e = 3; e < len; ++e) a += digits[e];
    const Result &res = small[len - 3][a][s % ten[3]];
    score *= res.p;
    score += res.q * (s / ten[3]);
    score += res.r;
    assert(res.c);
    s = s / ten[3] * ten[3] - res.c;
  }
  if (s < ten[3]) {
    const Result &res = small[0][0][s];
    score *= res.p;
    score += res.r;
    return score;
  }
  {
    auto digits = toDigits(s);
    const int len = digits.size();
    assert(3 < len); assert(len <= E);
    int a = 0;
    for (int e = 3; e < len; ++e) a += digits[e];
    for (int e = 3; e < len; ++e) {
      a -= digits[e];
      for (int &m = digits[e]; m >= 0; ) {
// cerr<<"e = "<<e<<"; s = "<<s<<", digits = "<<digits<<", a = "<<a<<", m = "<<m<<endl;
        const int c = ten[e] - s % ten[e];
        if (e == len - 1 && m == 0) {
          assert(a == 0);
          const Result &res = dp[e][0][0][c];
// cerr<<"  "<<e<<" "<<0<<" "<<0<<" "<<c<<": "<<res<<endl;
          score *= res.p;
          score += res.r;
          assert(!res.c);
          return score;
        } else {
          const Result &res = dp[e][len - e][a + m][c];
// cerr<<"  "<<e<<" "<<len-e<<" "<<a+m<<" "<<c<<": "<<res<<endl;
          score *= res.p;
          score += res.q * (s / ten[e]);
          score += res.r;
          assert(res.c);
          s += c;
          s -= ten[e];
          s -= res.c;
          --m;
        }
      }
      --a;
      --digits[e + 1];
    }
  }
  assert(false);
}

int main() {
  ten[0] = 1;
  for (int e = 1; e <= E; ++e) ten[e] = ten[e - 1] * 10;
  
  brt[0] = make_pair(1, 0);
  for (int s = 1; s <= LIM_BRUTE; ++s) {
    int len = 0, d = 0;
    for (int ss = s; ss; ss /= 10) {
      ++len;
      d += ss % 10;
    }
    brt[s] = make_pair(ten[len] * brt[s - d].first, s * brt[s - d].first + brt[s - d].second);
  }
cerr<<"brt[32] = "<<brt[32]<<endl;
  for (int s = 1; s <= LIM_BRUTE; ++s) {
    brtSum[s] = brtSum[s - 1] + brt[s].second;
  }
  
  {
    for (int f = 0; f <= E - 3; ++f) for (int a = f ? 1 : 0; a <= 9 * f; ++a) {
      for (int s = 0; s < ten[3]; ++s) {
        Result &ret = small[f][a][s];
        ret.p = 1;
        if (f || s) {
          ret.mul(ten[f]);
          ret.q += 1;
          ret.mul(ten[f ? 3 : (int)to_string(s).size()]);
          ret.r += s;
          int d = a;
          for (int g = 0; g < 3; ++g) d += s / ten[g] % 10;
          assert(d > 0);
          if (s < d) {
            ret.c = d - s;
          } else {
            const Result &res = small[f][a][s - d];
            ret.mul(res.p);
            ret.q += res.q;
            ret.r += res.r;
            ret.c = res.c;
          }
        }
      }
    }
  }
cerr<<"small[0][0][32] = "<<small[0][0][32]<<endl;
cerr<<"small[0][0][1] = "<<small[0][0][1]<<endl;
  {
    for (int f = 0; f <= E - 3; ++f) for (int a = f ? 1 : 0; a <= 9 * f; ++a) {
      for (int b = 1; b <= 9 * E; ++b) {
        dp[3][f][a][b] = small[f][a][ten[3] - b];
      }
    }
  }
  for (int e = 4; e <= E; ++e) {
    for (int f = 0; f <= E - e; ++f) for (int a = f ? 1 : 0; a <= 9 * f; ++a) {
      for (int b = 1; b <= 9 * E; ++b) {
        Result &ret = dp[e][f][a][b];
        ret.p = 1;
        ret.c = b;
        for (int m = 10; --m >= 0; ) {
          const Result &res = dp[e - 1][(f || m) ? (f + 1) : 0][a + m][ret.c];
// if(e==4&&f==0&&a==0&&b==1)cerr<<"HELP"<<__LINE__<<" "<<e-1<<" "<<((f || m) ? (f + 1) : 0)<<" "<<a+m<<" "<<ret.c<<": "<<res<<endl;
          ret.mul(res.p);
          ret.q += res.q * 10;
          ret.r += res.q * m;
          ret.r += res.r;
          ret.c = res.c;
        }
      }
    }
  }
  
  for (int numCases; ~scanf("%d", &numCases); ) { for (int caseId = 1; caseId <= numCases; ++caseId) {
    Int L, R;
    scanf("%lld%lld", &L, &R);
    
    Mint ans = 0;
    if (R <= LIM_BRUTE) {
      ans = brtSum[R] - brtSum[L - 1];
    } else {
      for (Int s = L; s <= R; ++s) {
        const Mint slv = solve(s);
        if (s <= LIM_BRUTE) {
          if (brt[s].second != slv) {
            cerr << s << ": " << brt[s] << " " << slv << endl;
          }
          assert(brt[s].second == slv);
        }
        ans += slv;
      }
    }
    printf("%u\n", ans.x);
  }
#ifndef LOCAL
  break;
#endif
  }
  return 0;
}

详细

Subtask #1:

score: 5
Accepted

Test #1:

score: 5
Accepted
time: 163ms
memory: 194964kb

input:

10
9653 62002
91160 95589
4602 60141
54240 79592
69170 95623
46733 68190
25361 84435
23506 99583
62553 65996
22099 81703

output:

103592019
222392703
236171250
287406393
478554731
117904238
522507555
617451444
277292124
553293749

result:

ok 10 numbers

Test #2:

score: 0
Accepted
time: 171ms
memory: 194932kb

input:

500
174 85257
53439 99201
25556 99022
59548 92909
61936 77935
35851 62882
67138 71164
42431 65794
15439 89519
5723 18456
23983 25568
22597 68086
23328 93569
9292 67330
18318 88994
84792 90364
13981 83990
21502 61839
4123 63779
498 68986
34607 65882
11483 67457
22349 94822
24528 42149
14737 16569
643...

output:

588662657
274087272
994096268
769521372
234323706
928183056
662030711
217503980
734291561
395959901
588662067
240307614
780366739
980869834
300892674
79160805
615092140
4805327
818222180
368256926
937099344
664493054
822178346
136725071
480882109
856568785
118890530
234462958
831460844
238212390
186...

result:

ok 500 numbers

Test #3:

score: 0
Accepted
time: 171ms
memory: 194624kb

input:

500
76018 100000
93967 99999
32658 99998
88768 99997
53643 99996
6743 99995
66089 99994
40514 99993
24204 99992
30127 99991
55799 99990
35717 99989
98626 99988
32251 99987
75425 99986
26188 99985
88810 99984
56572 99983
78303 99982
94046 99981
76956 99980
55343 99979
67855 99978
48154 99977
88369 99...

output:

966615136
849139888
6267017
916820590
521834522
922204325
838533981
670560015
961311832
212078764
499503191
129196363
987715820
900604607
573266380
598854085
678826229
560106902
885695117
182655480
986707578
531178447
47748447
914611030
683369442
290251694
778653294
214408897
337506302
29387069
8568...

result:

ok 500 numbers

Subtask #2:

score: 0
Wrong Answer

Test #4:

score: 10
Accepted
time: 169ms
memory: 194668kb

input:

5
14151615 14151615
50959220 50959220
177962208 177962208
173507309 173507309
608527742 608527742

output:

574888399
728657674
419976531
502012045
456375259

result:

ok 5 number(s): "574888399 728657674 419976531 502012045 456375259"

Test #5:

score: 0
Accepted
time: 161ms
memory: 194980kb

input:

5
441384319 441384319
606726578 606726578
100872719 100872719
290542038 290542038
290435521 290435521

output:

304014472
49910017
871510667
927387471
830052470

result:

ok 5 number(s): "304014472 49910017 871510667 927387471 830052470"

Test #6:

score: -10
Wrong Answer
time: 104ms
memory: 194684kb

input:

5
686934834 686934834
217972715 217972715
91760217 91760217
478910665 478910665
871116356 871116356

output:


result:

wrong output format Output file not found: ""

Subtask #3:

score: 0
Skipped

Dependency #2:

0%

Subtask #4:

score: 0
Skipped

Dependency #3:

0%

Subtask #5:

score: 0
Skipped

Dependency #1:

100%
Accepted

Dependency #2:

0%

Subtask #6:

score: 0
Skipped

Dependency #5:

0%