まあ式に直接与えられます:
またはコンボリューション:
$ FWT [A] =マージ(FWT [A0]、FWT [A0] + FWT [A1])$
$ UFWT [A '] =マージ(UFWT [A0']、UFWT [A1 '] - UFWT [A0'])$
コンボリューション:
$ FWT [A] =マージ(FWT [A0] + FWT [A1]、FWT [A1])$
$ UFWT [A '] =マージ(UFWT [A0'] - UFWT [A1 ']、UFWT [A1'])$
XOR畳み込み:
$ FWT [A] =マージ(FWT [A0] + FWT [A1]、FWT [A0] -FWT [A1])$
$ UFWT [A '] =マージ(\ FRAC {FWT [A0'] + FWT [A1 ']} {2}、\ FRAC {FWT [A0'] - FWT [A1「]} {2})$
コード:
#include <cstdioを> する#include <アルゴリズム> の#define N 19 の#defineは長い長いっ の#define MOD 998244353 の#define setIO(S)freopenは(S ".IN"、 "R"、標準入力) 名前空間stdを使用。 INT qpow(int型のx、int型のY) { int型TMP = 1。 (; Y、Y >> = 1、X =(LL)X * X%MOD)のための IF(Y&1)TMP =(LL)TMP * X%のMOD。 tmpに返します。 } INT LIM、INV、A [1 << N]、B [1 << N]、C [1 << N]、F [1 << N]、G [1 << N]。 無効FWT_or(int型*、int型OPT) { int型I、J、K。 (; I <I LIM << = 1、I = 1の)のために { (j = 0; J <LIM; jは+ = I << IF(OPT == 1)[I + J + K] = 1LL *([J + K] + [I + J + K])%のMOD。 他[I + J + K] = 1LL *([I + J + K] + MOD-[J + K])%のMOD。 // [J + K + I] =(LL)(1LL * [J + K + I] + 1LL * OPT * [J + K] + MOD)%のMOD。 } } } } ボイドFWT_and(INT *、INT OPT) { int型I、J、K。 (; I <LIM I << = 1、I = 1の)のために { ため(J = 0; J <LIM; jは+ = I << 1) { (k = 0; K <I; ++ k)に対する { ([J + K] + = 1LL *(OPT * [J + K + I] + MOD)%のMOD)%= MOD。 } } } } ボイドFWT_xor(INT *、INT OPT) { I、J、K int型。 (; I <LIM I << = 1、I = 1の)のために { ため(J = 0; J <LIM; jは+ = I << 1) { (k = 0; K <I; ++ k)に対する { INT TMP = A [J + K]。 [J + K] =(LL)([J + K] + [J + K + I])%のMOD。 [J + K + I] =(LL)(TMP-[J + K + I] + MOD)%のMOD。 IF(OPT == - 1) { [J + K] =(LL)INV * [J + K]%のMOD。 [J + K + I] =(LL)INV * [J + K + I]%のMOD。 } } } } } 無効test_or() F [I] = A [i]が、G [I] = B [i]が(; I <LIM ++ I I = 0)ため、 { 私は、jはint型。 FWT_or(F、1)、FWT_or(G、1)。 以下のための(I = 0、I <LIM; ++ I)F [I] = 1LL * F [I] * G [I]%のMOD。 FWT_or(F、-1)。 printf( "%dの"、F [i])と(++ I; I <I LIM = 0)ため、 printf( "\ n"は); } ボイドtest_and() { int型I、J。 F [I] = A [i]が、G [I] = B [i]が(; I <LIM ++ I I = 0)ため、 FWT_and(F、1)、FWT_and(G、1)。 以下のための(I = 0、I <LIM; ++ I)F [I] = 1LL * F [I] * G [I]%のMOD。 FWT_and(F、-1)。 printf( "%dの"、F [i])と(++ I; I <I LIM = 0)ため、 printf( "\ n"は); } ボイドtest_xor() { int型I、J。 F [I] = A [i]が、G [I] = B [i]が(; I <LIM ++ I I = 0)ため、 I <LIM;(I = 0のための FWT_xor(F、-1)。 printf( "%dの"、F [i])と(++ I; I <I LIM = 0)ため、 printf( "\ n"は); } int型のmain() { // setIO( "入力")。 int型I、J、N。 scanf関数( "%のD"、&N)、LIM = 1 << N、INV = qpow(2、MOD-2)。 scanf関数( "%D"、&A [i])と、A [I] =(A [i]の%MOD + MOD)%のMOD(; I <LIM ++ I I = 0)ため、 scanf関数( "%D"、&B [i])と、B [I] =(B [I]%MOD + MOD)%のMOD(; I <LIM ++ I I = 0)ため、 test_or()、test_and()、test_xor()。 0を返します。 }