QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#330976 | #8005. Crossing the Border | jnzg | ML | 239ms | 159964kb | C++14 | 4.1kb | 2024-02-17 21:30:39 | 2024-02-17 21:30:39 |
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];
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) { // 枚举右边
// cod(s2);
// if(s2 % 100 == 0) {
// cout << 1 << endl;
// }
lp(s, 0, (1 << L) - 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;
}
}
mst(h, 0);
}
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: 0ms
memory: 38448kb
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: 0
Accepted
time: 239ms
memory: 159964kb
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:
9391997 70
result:
ok 2 number(s): "9391997 70"
Test #3:
score: -100
Memory Limit Exceeded
input:
20 10000000 1289384 1416015 1692778 1966748 1747794 1708650 2885387 2925290 2516650 2410838 2202363 2092667 368691 407497 1897764 1902790 180541 224758 1089173 1075924 2005212 1743637 702568 566295 465783 369143 2722863 2902398 174068 150211 513930 519657 1634023 1313239 1133070 1040937 961394 11066...
output:
6331196 89