結果

問題 No.1901 bitwise xor convolution (characteristic 2)
ユーザー 👑 hos.lyrichos.lyric
提出日時 2022-04-12 21:34:54
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 1,998 ms / 4,000 ms
コード長 2,836 bytes
コンパイル時間 1,079 ms
コンパイル使用メモリ 111,588 KB
実行使用メモリ 17,664 KB
最終ジャッジ日時 2023-08-23 06:51:05
合計ジャッジ時間 11,182 ms
ジャッジサーバーID
(参考情報)
judge11 / judge15
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
4,376 KB
testcase_01 AC 1 ms
4,376 KB
testcase_02 AC 2 ms
4,376 KB
testcase_03 AC 1 ms
4,376 KB
testcase_04 AC 1 ms
4,380 KB
testcase_05 AC 1 ms
4,380 KB
testcase_06 AC 1 ms
4,376 KB
testcase_07 AC 1,998 ms
17,456 KB
testcase_08 AC 1,988 ms
17,664 KB
testcase_09 AC 1,969 ms
17,520 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

// #pragma GCC optimize ("Ofast")
// #pragma GCC optimize ("unroll-loops")
// #pragma GCC target ("avx")

#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 <map>
#include <numeric>
#include <queue>
#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> 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; }

#pragma GCC target("pclmul", "sse2", "sse4.1")
#include <emmintrin.h>
#include <smmintrin.h>
#include <wmmintrin.h>

__int64_t clmul(__int64_t x, __int64_t y) {
  __m128i x_ = _mm_set_epi64x(0, x);
  __m128i y_ = _mm_set_epi64x(0, y);
  __m128i z_ = _mm_clmulepi64_si128(x_, y_, 0);
  return _mm_extract_epi64(z_, 0);
}


using UInt = unsigned long long;

UInt readPoly() {
  UInt ret = 0;
  for (int e = 0; e < 32; ++e) {
    int x;
    scanf("%d", &x);
    ret |= ((UInt)x) << e;
  }
  return ret;
}


vector<UInt> mul(int n, vector<UInt> as, vector<UInt> bs) {
  vector<UInt> cs(1 << n, 0);
  if (n <= 4) {
    for (int ha = 0; ha < 1 << n; ++ha) for (int hb = 0; hb < 1 << n; ++hb) {
      cs[ha ^ hb] ^= clmul(as[ha], bs[hb]);
    }
  } else {
    --n;
    vector<UInt> as0(as.begin(), as.begin() + (1 << n));
    vector<UInt> bs0(bs.begin(), bs.begin() + (1 << n));
    vector<UInt> as1(as.begin() + (1 << n), as.end());
    vector<UInt> bs1(bs.begin() + (1 << n), bs.end());
    const auto cs0 = mul(n, as0, bs0);
    const auto cs1 = mul(n, as1, bs1);
    for (int h = 0; h < 1 << n; ++h) as0[h] ^= as1[h];
    for (int h = 0; h < 1 << n; ++h) bs0[h] ^= bs1[h];
    const auto cs2 = mul(n, as0, bs0);
    for (int h = 0; h < 1 << n; ++h) cs[h] = cs0[h] ^ cs1[h];
    for (int h = 0; h < 1 << n; ++h) cs[1 << n | h] = cs[h] ^ cs2[h];
  }
  return cs;
}

int main() {
  int N;
  vector<UInt> A, B;
  for (; ~scanf("%d", &N); ) {
    A.resize(1 << N); for (int h = 0; h < 1 << N; ++h) A[h] = readPoly();
    B.resize(1 << N); for (int h = 0; h < 1 << N; ++h) B[h] = readPoly();
    
    const auto C = mul(N, A, B);
    for (int h = 0; h < 1 << N; ++h) {
      for (int e = 0; e < 63; ++e) {
        if (e) putchar(' ');
        putchar('0' + (C[h] >> e & 1));
      }
      puts("");
    }
  }
  return 0;
}
0