QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#355548#7858. Basic Equation Solvingucup-team1191#TL 435ms3944kbC++209.2kb2024-03-16 20:10:222024-10-14 18:03:09

Judging History

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

  • [2024-10-14 18:03:09]
  • 管理员手动重测本题所有获得100分的提交记录
  • 测评结果:TL
  • 用时:435ms
  • 内存:3944kb
  • [2024-03-20 11:12:17]
  • hack成功,自动添加数据
  • (/hack/581)
  • [2024-03-16 20:10:22]
  • 评测
  • 测评结果:100
  • 用时:398ms
  • 内存:3912kb
  • [2024-03-16 20:10:22]
  • 提交

answer

#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
#define TIME (clock() * 1.0 / CLOCKS_PER_SEC)

const int MOD = 998'244'353;

using ull = unsigned long long;
template <int MD>
struct ModInt {
    using M = ModInt;
//    static int MD;
    int v;
    ModInt(ll _v = 0) { set_v(int(_v % MD + MD)); }
    inline M& set_v(int _v) {
        v = (_v < MD) ? _v : _v - MD;
        return *this;
    }
    inline explicit operator bool() const { return v != 0; }
    inline M operator-() const { return M() - *this; }
    inline M operator+(const M& r) const { return M().set_v(v + r.v); }
    inline M operator-(const M& r) const { return M().set_v(v + MD - r.v); }
    inline M operator*(const M& r) const { return M().set_v(int((ull)v * r.v % MD)); }
    inline M operator/(const M& r) const { return *this * r.inv(); }
    inline M& operator+=(const M& r) { return *this = *this + r; }
    inline M& operator-=(const M& r) { return *this = *this - r; }
    inline M& operator*=(const M& r) { return *this = *this * r; }
    inline M& operator/=(const M& r) { return *this = *this / r; }
    inline bool operator==(const M& r) const { return v == r.v; }
    inline bool operator!=(const M& r) const { return v != r.v; }
    inline M inv() const;
    inline friend istream& operator>>(istream& is, M& r) { ll x; is >> x; r = M(x); return is; }
    inline friend ostream& operator<<(ostream& os, const M& r) { return os << r.v; }
};

template<int MD>
ModInt<MD> pow(ModInt<MD> x, ll n) {
//ModInt pow(ModInt x, ll n) {
    ModInt<MD> r = 1;
    //ModInt r = 1;
    while (n) {
        if (n & 1) r *= x;
        x *= x;
        n >>= 1;
    }
    return r;
}

template<int MD>
ModInt<MD> ModInt<MD>::inv() const { return pow(*this, MD - 2); }
//ModInt ModInt::inv() const { return pow(*this, MD - 2); }

// if MD is from input
// this line is necessary, read later as you wish
//int ModInt::MD;

using Mint = ModInt<MOD>;
//using Mint = ModInt;

tuple<bool, string, string> read() {
    string s;
    cin >> s;
    int p = -1;
    for (int i = 0; i < (int)s.size(); i++) {
        if (s[i] == '=' || s[i] == '>' || s[i] == '<') {
            p = i;
        }
    }
    assert(p != -1);
    auto a = s.substr(0, p);
    auto b = s.substr(p + 1, (int)s.size() - p - 1);
    while (a.size() < b.size()) {
        a = "0" + a;
    }
    while (b.size() < a.size()) {
        b = "0" + b;
    }
    if (s[p] == '<') {
        swap(a, b);
    }
    return make_tuple(s[p] == '=', a, b);
}

const int S = 36;

int getnum(char x) {
    if (x >= '0' && x <= '9') {
        return x - '0';
    }
    return 10 + (x - 'A');
}

int par[S], rg[S];
vector<tuple<int, int, int>> history;

int find_set(int i) {
    if (i == par[i]) {
        return i;
    }
    return find_set(par[i]);
}

void merge(int i, int j) {
    i = find_set(i);
    j = find_set(j);
    if (i == j) {
        history.emplace_back(-1, -1, -1);
        return;
    }
    if (rg[i] > rg[j]) {
        swap(i, j);
    }
    history.emplace_back(i, par[i], rg[j]);
    par[i] = j;
    if (rg[i] == rg[j]) {
        rg[j]++;
    }
}

void undo() {
    auto op = history.back();
    history.pop_back();
    if (get<0>(op) == -1) {
        return;
    }
    int i = get<0>(op);
    int j = par[i];
    par[i] = get<1>(op);
    rg[j] = get<2>(op);
}

bool check_dig() {
    ll mask = 0;
    for (int i = 0; i < 10; i++) {
        ll idx = find_set(i);
        if ((mask >> idx) & 1LL) {
            return false;
        }
        mask |= (1LL << idx);
    }
    return true;
}

vector<pair<int, int>> edges;

int dig[S];
int cnt[S];

int p2[S];

int fnd(int i) {
    if (i == p2[i]) {
        return i;
    }
    return p2[i] = fnd(p2[i]);
}

void mrg(int i, int j) {
    i = fnd(i);
    j = fnd(j);
    if (i == j) {
        return;
    }
    p2[i] = j;
}

vector<int> in[S];
vector<pair<int, int>> ein[S];

int into[S];

bool good[(1 << 11)];
bool can[10][(1 << 11)];

Mint dp[2][(1 << 11)];

Mint func(int cmp) {
    if (ein[cmp].empty()) {
        int x = in[cmp][0];
        if (dig[x] != -1) {
            return 1;
        } else {
            return 10;
        }
    }

    int sz = in[cmp].size();
    for (int i = 0; i < sz; i++) {
        into[in[cmp][i]] = i;
    }

    for (int mask = 0; mask < (1 << sz); mask++) {
        good[mask] = true;
        for (auto [s, f] : ein[cmp]) {
            s = into[s];
            f = into[f];
            if (((mask >> f) & 1) == 1 && ((mask >> s) & 1) == 0) {
                good[mask] = false;
                break;
            }
        }
    }

    for (int d = 0; d < 10; d++) {
        for (int mask = 0; mask < (1 << sz); mask++) {
            can[d][mask] = true;
            for (int s : in[cmp]) {
                int u = dig[s];
                if (u != -1) {
                    s = into[s];
                    if ((mask >> s) & 1) {
                        if (u != d) {
                            can[d][mask] = false;
                            break;
                        }
                    }
                }
            }
            if (!can[d][mask]) {
                continue;
            }
            for (auto [s, f]: ein[cmp]) {
                s = into[s];
                f = into[f];
                if (((mask >> f) & 1) == 1 && ((mask >> s) & 1) == 1) {
                    can[d][mask] = false;
                    break;
                }
            }
        }
    }

    memset(dp[0], 0, sizeof(dp[0]));
    dp[0][0] = 1;
    for (int d = 9; d >= 0; d--) {
        memset(dp[d & 1], 0, sizeof(dp[d & 1]));
        for (int mask = 0; mask < (1 << sz); mask++) {
            if (good[mask]) {
                for (int sub = mask; sub > 0; sub = (sub - 1) & mask) {
                    if (good[sub] && can[d][sub ^ mask]) {
                        dp[d & 1][mask] += dp[(d + 1) & 1][sub];
                    }
                }
                {
                    int sub = 0;
                    if (good[sub] && can[d][sub ^ mask]) {
                        dp[d & 1][mask] += dp[(d + 1) & 1][sub];
                    }
                }
            }
        }
    }

    return dp[0][(1 << sz) - 1];
}

Mint calc() {
    memset(dig, -1, sizeof(dig));
    memset(cnt, 0, sizeof(cnt));
    for (int i = 0; i < 10; i++) {
        int c = find_set(i);
        dig[c] = i;
    }
    for (int i = 10; i < S; i++) {
        int c = find_set(i);
        cnt[c]++;
    }

    for (int i = 0; i < S; i++) {
        p2[i] = i;
    }
    for (const auto& t : edges) {
        int x = find_set(t.first);
        int y = find_set(t.second);
        if (x == y) {
            return 0;
        }
        mrg(x, y);
    }

    for (int i = 0; i < S; i++) {
        in[i].clear();
        ein[i].clear();
    }
    for (int i = 0; i < S; i++) {
        if (cnt[i] > 0 || dig[i] != -1) {
            in[fnd(i)].emplace_back(i);
        }
    }
    for (const auto& t : edges) {
        int x = find_set(t.first);
        int y = find_set(t.second);
        int cmp = fnd(x);
        ein[cmp].emplace_back(x, y);
    }

    Mint ans = 1;
    for (int x = 0; x < S; x++) {
        if (!in[x].empty()) {
            auto val = func(x);
            //cerr << x << " " << val << "??\n";
            ans *= val;
            if (ans == 0) {
                return 0;
            }
        }
    }

    return ans;
}

Mint ans;
vector<pair<string, string>> pr;

void gen(int b) {
    if (b == pr.size()) {
        ans += calc();
        return;
    }
    int cnt = pr[b].first.size();
    for (int i = 0; i < (int)pr[b].first.size(); i++) {
        int x = getnum(pr[b].first[i]);
        int y = getnum(pr[b].second[i]);
        edges.emplace_back(x, y);
        gen(b + 1);
        edges.pop_back();
        merge(x, y);
        if (!check_dig()) {
            cnt = i + 1;
            break;
        }
    }
    for (int it = 0; it < cnt; it++) {
        undo();
    }
}

void solve() {
    int n;
    cin >> n;

    vector<tuple<bool, string, string>> constr;
    for (int i = 0; i < n; i++) {
        constr.emplace_back(read());
        //cout << get<0>(constr.back()) << " " << get<1>(constr.back()) << " " << get<2>(constr.back()) << "\n";
    }

    iota(par, par + S, 0);
    memset(rg, 0, sizeof(rg));

    pr.clear();
    for (const auto& item : constr) {
        if (get<0>(item)) {
            auto a = get<1>(item);
            auto b = get<2>(item);
            for (int i = 0; i < (int)a.size(); i++) {
                merge(getnum(a[i]), getnum(b[i]));
            }
        } else {
            pr.emplace_back(get<1>(item), get<2>(item));
        }
    }

    if (!check_dig()) {
        cout << "0\n";
        return;
    }

    ans = 0;
    gen(0);

    cout << ans << "\n";
}

int main() {
#ifdef ONPC
    freopen("input", "r", stdin);
#endif
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

    int t = 1;
    //cin >> t;
    while (t--) {
        solve();
    }

    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 3620kb

input:

1
P=NP

output:

766136394

result:

ok single line: '766136394'

Test #2:

score: 0
Accepted
time: 0ms
memory: 3704kb

input:

1
2000CNY>3000USD

output:

0

result:

ok single line: '0'

Test #3:

score: 0
Accepted
time: 0ms
memory: 3864kb

input:

4
AB>CD
E<A
BC>FF
EF>F1

output:

23645065

result:

ok single line: '23645065'

Test #4:

score: 0
Accepted
time: 0ms
memory: 3676kb

input:

2
BC>DD
BD<EA

output:

27271695

result:

ok single line: '27271695'

Test #5:

score: 0
Accepted
time: 0ms
memory: 3864kb

input:

3
CE>ED
CC>BA
BB<AC

output:

426829091

result:

ok single line: '426829091'

Test #6:

score: 0
Accepted
time: 8ms
memory: 3644kb

input:

10
KG<EI
EJ>DA
EB<IH
EB>JG
KF<CF
JC>FC
IC<BJ
FI>HH
KD>AH
AE>GJ

output:

87744507

result:

ok single line: '87744507'

Test #7:

score: 0
Accepted
time: 21ms
memory: 3904kb

input:

10
EK<GM
EL<DC
DH>IH
EF>BL
IM<LL
EH<JA
DJ<AL
GL>MB
DB>FM
AI<HA

output:

665533468

result:

ok single line: '665533468'

Test #8:

score: 0
Accepted
time: 39ms
memory: 3676kb

input:

10
OD<FK
FJ>NL
NH>KB
KM>CA
CI>JH
CI<AH
CE>GI
CO<EG
FA>HA
FA<IJ

output:

878923575

result:

ok single line: '878923575'

Test #9:

score: 0
Accepted
time: 435ms
memory: 3712kb

input:

10
YH>UQ
UQ>FD
YZ>MK
FY<GO
YV<QW
UV<VJ
UZ>EB
EQ>LX
VP>ZF
LZ>TS

output:

867624189

result:

ok single line: '867624189'

Test #10:

score: 0
Accepted
time: 330ms
memory: 3588kb

input:

10
YH<UL
UD<FY
FK<MU
MM<GO
GG<QW
QJ<VQ
VZ<EB
EG<LX
LZ<ZP
ZV<TS

output:

57935948

result:

ok single line: '57935948'

Test #11:

score: 0
Accepted
time: 1ms
memory: 3936kb

input:

6
EDDC>AB5A
B<C
E9A9B>CACAA
DE2>A0D
DBCDAC>AED3D5
AAA>BB5

output:

169889581

result:

ok single line: '169889581'

Test #12:

score: 0
Accepted
time: 0ms
memory: 3636kb

input:

9
C<B
A>B
FDF2<FBDB
DB>B4
CF>DA
EF4<D1A
B8<A5
B3>BF
FFA<D5B

output:

0

result:

ok single line: '0'

Test #13:

score: 0
Accepted
time: 0ms
memory: 3940kb

input:

5
SP6<GCT
J0RFZ<ZZLUX
UDY7<UEVX
C1CQ>FXTG
SOCT07<MEABU8

output:

603602671

result:

ok single line: '603602671'

Test #14:

score: 0
Accepted
time: 3ms
memory: 3940kb

input:

7
F>M
G8F<KC5
F06<E8G
H5J<BJE
M8CDE<DIGMC
AE08>EFI7
DM>CI

output:

821791712

result:

ok single line: '821791712'

Test #15:

score: 0
Accepted
time: 2ms
memory: 3944kb

input:

10
PS1>O9O
G76>F8S
J<S
SB>Y4
WS<VM
E<N
ZR<CV
G8T>XPJ
J<A
KT<LS

output:

97272892

result:

ok single line: '97272892'

Test #16:

score: 0
Accepted
time: 0ms
memory: 3676kb

input:

4
K1TVV0>TOB4QTH
E5U5C9>QGDEGU
Q9LW3SK>LWFRP
DXUQM=V4N4

output:

467745652

result:

ok single line: '467745652'

Test #17:

score: 0
Accepted
time: 1ms
memory: 3636kb

input:

5
BC5F<AC3F
FA4<D48306EDD
EFDD>FDABE
CF5C<AFDDB
FAF<C387

output:

808992671

result:

ok single line: '808992671'

Test #18:

score: 0
Accepted
time: 0ms
memory: 3644kb

input:

1
ABCDEFGHIJKLMNOPQRSTUVWX>BCDEFGHIJKLMNOPQRSTUVWXY

output:

835948861

result:

ok single line: '835948861'

Test #19:

score: 0
Accepted
time: 0ms
memory: 3676kb

input:

3
A=A
00109=109
XX=Z

output:

276262510

result:

ok single line: '276262510'

Test #20:

score: 0
Accepted
time: 0ms
memory: 3676kb

input:

2
ABCDEFGHIJKL=CDEFGHIJKLMN
OPQRSTUVWXYZ=RSTUVWXYZOPQ

output:

100000

result:

ok single line: '100000'

Test #21:

score: 0
Accepted
time: 4ms
memory: 3900kb

input:

9
N=A8
TT<QO3G
LS>JV
TSG>U5F
D<A934
FK<HKG
O>S1
GT<BBCX
SG>S

output:

929594610

result:

ok single line: '929594610'

Test #22:

score: 0
Accepted
time: 0ms
memory: 3680kb

input:

0

output:

673653469

result:

ok single line: '673653469'

Test #23:

score: 0
Accepted
time: 0ms
memory: 3936kb

input:

3
AB<CD
AC<BD
AD<BC

output:

219041723

result:

ok single line: '219041723'

Extra Test:

score: -3
Extra Test Failed : Time Limit Exceeded on 4

input:

10
A<BCD
E<FGH
I<JKL
M<NOP
Q<RST
U<VWX
Y<ZAB
C<DEF
G<HIJ
K<LMN

output:


result: