QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#330911#8005. Crossing the BorderjnzgRE 3ms69856kbC++144.0kb2024-02-17 20:48:322024-02-17 20:48:33

Judging History

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

  • [2024-02-17 20:48:33]
  • 评测
  • 测评结果:RE
  • 用时:3ms
  • 内存:69856kb
  • [2024-02-17 20:48:32]
  • 提交

answer

#include <bits/stdc++.h>
#define ll long long
#define db double
#define ldb long double
#define lp(i, j, n) for(int i = j; i <= n; ++i)
#define dlp(i, n, j) for(int i = n; i >= j; --i)
#define mst(n, v) memset(n, v, sizeof(n))
#define mcy(n, v) memcpy(n, v, sizeof(v))
#define INF 1e18
#define MAX4 0x3f3f3f3f
#define MAX8 0x3f3f3f3f3f3f3f3f
#define pii pair<int, int>
#define pll pair<ll, ll>
#define co(x) cout << (x) << ' '
#define cod(x) cout << (x) << endl
#define lc(x) ((x) << 1)
#define rc(x) ((x) << 1 ^ 1)
#define ls ch[x][0]
#define rs ch[x][1]
#define fi first
#define se second
#define pb(x) emplace_back(x)

using namespace std;

const int N = 23, M = 12;
const ll MOD = 998244353;

struct node {
    ll sum, num, cst;

    bool operator < (const node & t) const { return sum < t.sum; }
    bool operator < (const ll t) const { return sum < t; }
};

struct ipt { int a, b; } tmp[N];

int n, m, a[N], b[N], L, R;
ll rsm[1 << M], lsm[1 << M], f[2][1 << M], g[2][1 << N];
vector<node> h[1 << M];
/*
f[0/1][s]: 右边最小代价和方案数
h[s]: 为 s 时左边与(右边所有子集)按 sum{a} 排序后的代价前缀最小值,和对应方案数
g[0/1][s]: 为 s 时全局最小代价和方案数
lsm[s]: 左边为 s 时 a[i] 和
rsm[s]: 右边为 s 时 a[i] 和
*/

signed main() {
    // freopen(".in", "r", stdin);
    // freopen(".out", "w", stdout);
#ifndef READ
    ios::sync_with_stdio(false);
    cin.tie(0);
#endif
    cin >> n >> m;
    lp(i, 1, n) cin >> tmp[i].a >> tmp[i].b;
    sort(tmp + 1, tmp + 1 + n, [&] (ipt t1, ipt t2) { return t1.b > t2.b; });
    lp(i, 1, n) a[i] = tmp[i].a, b[i] = tmp[i].b;
    L = n / 2, R = n - L;
    mst(f[0], 0x3f), mst(g[0], 0x3f), f[0][0] = 0, f[1][0] = 1;
    lp(s, 0, (1 << R) - 1) {
        lp(i, 1, R) rsm[s] += 1 << i - 1 & s ? a[L + i] : 0;
        for(int i = s; i; i = s & i - 1) {      // 转移 f
            if(rsm[i] <= m && (s & -s) == (i & -i)) {
                ll v = f[0][s ^ i] + b[L + (int)log2(i & -i) + 1];
                if(v < f[0][s]) f[0][s] = v, f[1][s] = f[1][s ^ i];
                else if(v == f[0][s]) (f[1][s] += f[1][s ^ i]) %= MOD;
            }
        }
        // co(s), cod(f[0][s]);
        g[0][s << L] = f[0][s], g[1][s << L] = f[1][s];
    }
    // co(f[0][(1 << R) - 1]), cod(f[1][(1 << R) - 1]);
    lp(s, 0, (1 << L) - 1) {    // 枚举左边
        lp(i, 1, L) lsm[s] += 1 << i - 1 & s ? a[i] : 0;
        lp(s2, 0, (1 << R) - 1) {       // 枚举右边
            ll S = s2 << L | s;
            for(int i = s; i; i = s & i - 1) {      // 枚举左边子集并转移 g
                if(lsm[i] <= m && (s & -s) == (i & -i)) {
                    auto t = prev(upper_bound(h[S ^ i].begin(), h[S ^ i].end(), (node) { m - lsm[i], 0ll, 0ll }));
                    ll v = t->cst + b[(int)log2(i & -i) + 1];
                    // co(t->sum), co(t->cst), cod(t->num);
                    // co(v), co(g[0][S]), cod(t->num);
                    if(v < g[0][S]) g[0][S] = v, g[1][S] = t->num;
                    else if(v == g[0][S]) (g[1][S] += t->num) %= MOD;
                }
            }
            // co(S), co(s), co(s2), co(g[0][S]), cod(g[1][S]);
            for(int i = s2; ; i = s2 & i - 1) {     // 处理 h
                if(rsm[i] <= m) {
                    h[S].push_back({ rsm[i], g[1][S ^ (i << L)], g[0][S ^ (i << L)] });
                    // co(rsm[i]), co(g[1][S ^ (i << L)]), cod(g[0][S ^ (i << L)]);
                }
                if(!i) break;
            }
            sort(h[S].begin(), h[S].end());
            lp(i, 1, (int)h[S].size() - 1) {    // 做代价前缀最小值并计算方案数前缀和
                if(h[S][i].cst > h[S][i - 1].cst) h[S][i].cst = h[S][i - 1].cst, h[S][i].num = h[S][i - 1].num;
                else if(h[S][i].cst == h[S][i - 1].cst) (h[S][i].num += h[S][i - 1].num) %= MOD;
            }
        }
    }
    cout << g[0][(1 << n) - 1] << ' ' << g[1][(1 << n) - 1] % MOD << endl;
    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 3ms
memory: 69856kb

input:

5 5
3 5
1 4
2 3
2 2
2 1

output:

9 4

result:

ok 2 number(s): "9 4"

Test #2:

score: -100
Runtime Error

input:

18 10000000
956231 904623
1692946 1796774
1081323 1170319
3218792 2542661
3183376 3037270
1869132 1442561
35436 35018
1564635 1939950
1847344 2006043
755870 899310
1671882 2057413
1369264 1338951
3132483 3504034
2056224 1825640
1840949 1562071
1514040 1405352
2300821 2421801
2466540 3004920

output:


result: