QOJ.ac
QOJ
ID | Submission ID | Problem | Hacker | Owner | Result | Submit time | Judge time |
---|---|---|---|---|---|---|---|
#507 | #305128 | #8005. Crossing the Border | hos_lyric | hos_lyric | Failed. | 2024-01-14 18:50:48 | 2024-01-14 18:50:50 |
Details
Extra Test:
Accepted
time: 4309ms
memory: 493944kb
input:
22 6016 3009 40000001 3008 40000002 3007 40000004 3006 40000008 3005 40000016 3004 40000032 2010 40000064 2009 40000128 2008 40000256 2007 40000512 2006 40001024 2005 40002048 2004 40004096 2003 40008192 2002 40016384 1006 40032768 1005 40065536 1004 40131072 1003 40262144 1002 40524288 1001 4104857...
output:
322134700 2
result:
ok 2 number(s): "322134700 2"
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#305128 | #8005. Crossing the Border | hos_lyric | AC ✓ | 3373ms | 494784kb | C++14 | 4.6kb | 2024-01-14 18:48:59 | 2024-01-14 18:48:59 |
answer
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
using namespace std;
using Int = long long;
template <class T1, class T2> ostream &operator<<(ostream &os, const pair<T1, T2> &a) { return os << "(" << a.first << ", " << a.second << ")"; };
template <class T> ostream &operator<<(ostream &os, const vector<T> &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; }
template <class T> void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; }
template <class T> bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; }
template <class T> bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; }
#define COLOR(s) ("\x1b[" s "m")
// as * bs
// ZT: T[2^n][n+1]
template <class T, class ZT>
vector<T> setMul(int n, const vector<T> &as, const vector<T> &bs, ZT zas, ZT zbs) {
assert(static_cast<int>(as.size()) == 1 << n);
assert(static_cast<int>(bs.size()) == 1 << n);
// ranked
for (int h = 0; h < 1 << n; ++h) {
memset(zas[h], 0, (n + 1) * sizeof(T));
zas[h][__builtin_popcount(h)] = as[h];
}
for (int h = 0; h < 1 << n; ++h) {
memset(zbs[h], 0, (n + 1) * sizeof(T));
zbs[h][__builtin_popcount(h)] = bs[h];
}
// zeta
for (int w = 1; w < 1 << n; w <<= 1) {
for (int h0 = 0; h0 < 1 << n; h0 += w << 1) for (int h = h0; h < h0 + w; ++h) {
for (int k = 0; k <= n; ++k) zas[h + w][k] += zas[h][k];
}
}
for (int w = 1; w < 1 << n; w <<= 1) {
for (int h0 = 0; h0 < 1 << n; h0 += w << 1) for (int h = h0; h < h0 + w; ++h) {
for (int k = 0; k <= n; ++k) zbs[h + w][k] += zbs[h][k];
}
}
// product
for (int h = 0; h < 1 << n; ++h) {
for (int k = n; k >= 0; --k) {
T t = 0;
for (int l = 0; l <= k; ++l) t += zas[h][l] * zbs[h][k - l];
zas[h][k] = t;
}
}
// moebius
for (int w = 1; w < 1 << n; w <<= 1) {
for (int h0 = 0; h0 < 1 << n; h0 += w << 1) for (int h = h0; h < h0 + w; ++h) {
for (int k = 0; k <= n; ++k) zas[h + w][k] -= zas[h][k];
}
}
// unrank
vector<T> cs(1 << n);
for (int h = 0; h < 1 << n; ++h) cs[h] = zas[h][__builtin_popcount(h)];
return cs;
}
constexpr int MO = 998244353;
constexpr int MAX_N = 22;
constexpr int INF = 1001001001;
Int zas[1 << MAX_N][MAX_N + 1];
Int zbs[1 << MAX_N][MAX_N + 1];
int N, W;
vector<pair<int, int>> P;
int main() {
for (; ~scanf("%d%d", &N, &W); ) {
P.resize(N);
for (int i = 0; i < N; ++i) {
scanf("%d%d", &P[i].second, &P[i].first);
}
sort(P.begin(), P.end());
vector<int> sums(1 << N, 0);
for (int i = 0; i < N; ++i) {
for (int h = 0; h < 1 << i; ++h) {
sums[h | 1 << i] = sums[h] + P[i].second;
}
}
// dp[h]: used h
vector<pair<int, Int>> dp(1 << N, make_pair(INF, 0));
for (int h = 1 << (N - 1); h < 1 << N; ++h) if (sums[h] <= W) {
dp[h] = make_pair(P[N - 1].first, 1);
}
for (int i = N - 1; --i >= 0; ) {
auto crt = dp.end() - (1 << (i + 1));
auto nxt = dp.end() - (1 << i);
vector<int> vals(1 << i);
for (int h = 0; h < 1 << i; ++h) vals[h] = crt[h].first;
sort(vals.begin(), vals.end());
vals.erase(unique(vals.begin(), vals.end()), vals.end());
cerr<<i<<": "<<vals.size()<<endl;
vector<Int> fs(1 << i, 0);
for (int h = 0; h < 1 << i; ++h) if (sums[h | 1 << i] <= W) fs[h] = 1;
for (const int val : vals) if (val < INF) {
const int cost = P[i].first + val;
vector<Int> gs(1 << i, 0);
for (int h = 0; h < 1 << i; ++h) if (crt[h].first == val) gs[h] = crt[h].second;
const auto prod = setMul(i, fs, gs, zas, zbs);
for (int h = 0; h < 1 << i; ++h) if (prod[h]) {
if (nxt[h].first > cost) {
nxt[h].first = cost;
nxt[h].second = prod[h];
} else if (nxt[h].first == cost) {
nxt[h].second += prod[h];
}
}
}
}
printf("%d %lld\n", dp.back().first, dp.back().second % MO);
}
return 0;
}