QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#331017 | #8005. Crossing the Border | jnzg | WA | 0ms | 36516kb | C++14 | 4.2kb | 2024-02-17 22:16:46 | 2024-02-17 22:16:47 |
Judging History
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