QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#308735#8005. Crossing the Borderhos_lyricWA 84ms37052kbC++144.0kb2024-01-20 12:15:202024-01-20 12:15:20

Judging History

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

  • [2024-01-20 12:15:20]
  • 评测
  • 测评结果:WA
  • 用时:84ms
  • 内存:37052kb
  • [2024-01-20 12:15:20]
  • 提交

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")


constexpr int MO = 998244353;
constexpr int MAX_N = 22;

int N, W;
vector<pair<int, int>> P;

vector<int> CSum, WSum;

template <class T> void zeta(T zs, int n, int m, int h0) {
  const int pop0 = __builtin_popcount(h0);
  if (m) {
    --m;
    for (int h = h0; h < h0 + (1 << m); ++h) {
      const int pop = __builtin_popcount(h);
      for (int k = pop - pop0; k <= pop; ++k) zs[h | 1 << m][k] += zs[h][k];
    }
    zeta(zs, n, m, h0);
    zeta(zs, n, m, h0 | 1 << m);
  }
}
template <class T> void init(T zs, int n) {
  for (int p = 0; p < 1 << n; ++p) {
    fill(zs[p], zs[p] + (n + 1), 0);
    if (WSum[p | 1 << n] <= W) {
      zs[p][__builtin_popcount(p)] = 1;
    }
  }
  zeta(zs, n, n, 0);
}

/*
  zas: ways to have ...
  after processing [i, N),
    mask for [0, i): used items
    mask for [i, N-1): saved costs
  keep:
    ranked poly
    zeta'ed for [0, i)
*/
Int zas[1 << (MAX_N - 1)][(MAX_N - 1) + 1];
int zbs[1 << (MAX_N - 2)][(MAX_N - 2) + 1];

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());
    
    CSum.assign(1 << N, 0);
    WSum.assign(1 << N, 0);
    for (int i = 0; i < N; ++i) {
      for (int h = 0; h < 1 << i; ++h) {
        CSum[h | 1 << i] = CSum[h] + P[i].first;
        WSum[h | 1 << i] = WSum[h] + P[i].second;
      }
    }
    
    init(zas, N - 1);
    for (int i = N - 1; --i >= 0; ) {
      init(zbs, i);
      for (int q = 0; q < 1 << (N - 1); q += (1 << (i + 1))) {
        /*
          current: (0, 0+1)
          0: convolve
          1: save
        */
        for (int p = 0; p < 1 << i; ++p) {
          const int h0 = p | q;
          const int h1 = p | 1 << i | q;
          for (int k = 0; k <= N - 1; ++k) {
            zas[h1][k] -= zas[h0][k];
          }
          const int pop = __builtin_popcount(h0);
          for (int k = N - 1; k >= pop; --k) {
            Int t = 0;
            for (int l = max(0, k - i); l <= k; ++l) t += zas[h0][l] * zbs[p][k - l];
            zas[h0][k] = t;
          }
        }
      }
// cerr<<"DONE i = "<<i<<endl;
// for(int p=0;p<1<<(N-1);++p){cerr<<"zas["<<p<<"] = ";pv(zas[p],zas[p]+N);}
    }
    
    vector<Int> ways(1 << (N - 1));
    for (int h = 0; h < 1 << (N - 1); ++h) {
      ways[h] = zas[h][__builtin_popcount(h)];
    }
// cerr<<"ways = "<<ways<<endl;
    
    int ans = CSum.back() + 1;
    Int way = 0;
    for (int h = 0; h < 1 << (N - 1); ++h) if (ways[h]) {
      const int cost = CSum.back() - CSum[h];
      if (ans > cost) {
        ans = cost;
        way = ways[h];
      } else if (ans == cost) {
        way += ways[h];
      }
    }
    printf("%d %lld\n", ans, way % MO);
  }
  return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 1ms
memory: 5876kb

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
Wrong Answer
time: 84ms
memory: 37052kb

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:

7452047 -1053

result:

wrong answer 1st numbers differ - expected: '9391997', found: '7452047'