QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#331017#8005. Crossing the BorderjnzgWA 0ms36516kbC++144.2kb2024-02-17 22:16:462024-02-17 22:16:47

Judging History

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

  • [2024-02-17 22:16:47]
  • 评测
  • 测评结果:WA
  • 用时:0ms
  • 内存:36516kb
  • [2024-02-17 22:16:46]
  • 提交

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 {
    int sum, num, cst;

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

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

int n, m, a[N], b[N], L, R;
int rsm[1 << M], lsm[1 << M];
int f[2][1 << M], g[2][1 << N];
node h[1 << M][1 << M]; int hn[1 << M];
int od[1 << M][1 << M], odn[1 << M];
int od2[1 << M][1 << M], od2n[1 << M], lg[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;
    ll t1 = clock();
    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(i, 0, R - 1) lg[1 << i] = i;
    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 + lg[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;
            }
        }
        g[0][s << L] = f[0][s], g[1][s << L] = f[1][s];
    }
    int kk = 0;
    lp(s, 0, (1 << L) - 1) {
        lp(i, 1, L) lsm[s] += 1 << i - 1 & s ? a[i] : 0;
        for(int i = s; i; i = s & i - 1) {
            if(lsm[i] <= m && (s & -s) == (i & -i)) od[s][++odn[s]] = i;
        }
        sort(od[s] + 1, od[s] + 1 + odn[s], [&] (int t1, int t2) { return lsm[t1] > lsm[t2]; });
        kk += odn[s];
    }
    lp(s, 0, (1 << R) - 1) {
        for(int i = s; ; i = s & i - 1) {
            if(rsm[i] <= m) od2[s][++od2n[s]] = i;
            if(!i) break;
        }
        sort(od2[s] + 1, od2[s] + 1 + od2n[s], [&] (int t1, int t2) { return rsm[t1] < rsm[t2]; });
    }
    lp(s2, 0, (1 << R) - 1) {       // 枚举右边
        lp(s, 0, (1 << L) - 1) {        // 枚举左边
            int S = s2 << L | s, j = 1;
            lp(k, 1, odn[s]) {      // 枚举左边子集并转移 g
                int i = od[s][k];
                while(j < hn[s ^ i] && h[s ^ i][j + 1].sum <= m - lsm[i]) ++j;
                ll v = h[s ^ i][j].cst + b[lg[i & -i] + 1];
                if(v < g[0][S]) g[0][S] = v, g[1][S] = h[s ^ i][j].num;
                else if(v == g[0][S]) (g[1][S] += h[s ^ i][j].num) %= MOD;
            }
            lp(k, 1, od2n[s2]) {     // 处理 h
                int i = od2[s2][k];
                h[s][++hn[s]] = { rsm[i], g[1][S ^ (i << L)], g[0][S ^ (i << L)] };
            }
            lp(i, 2, hn[s]) {    // 做代价前缀最小值并计算方案数前缀和
                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;
            }
        }
        lp(s, 0, (1 << L) - 1) { hn[s] = 0; }
    }
    cout << g[0][(1 << n) - 1] << ' ' << g[1][(1 << n) - 1] % MOD << endl;
    cod(clock() - t1);
    return 0;
}

详细

Test #1:

score: 0
Wrong Answer
time: 0ms
memory: 36516kb

input:

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

output:

9 4
11123

result:

wrong answer Output contains longer sequence [length = 3], but answer contains 2 elements