kmjp's blog

競技プログラミング参加記です

yukicoder : No.1901 bitwise xor convolution (characteristic 2)

言われてみればそうだ。
https://yukicoder.me/problems/no/1901

問題

2^N要素からなる、D(=31)次多項式の列A,Bが与えられる。各係数は0か1である。
2^N要素からなる2D次多項式Cを、以下のように定める。
 \displaystyle C_k := \left( \sum_{i \oplus j = k} A_i B_j \right) \bmod 2

Cを求めよ。

解法

Editorialでいう解法2ベースの解き方で行くと、最後のmod 2はなくても解ける。
A,B,Cが多項式ではなく整数だった場合、下記記事のFast Walsh–Hadamard transformのところの要領で解ける。
毎回1/√2を掛けるのはやめ、最後にまとめて2^Nで割ってしまえばよい。
Fast Fourier Transform and variations of it

今回A,B,Cは多項式になるが、それでも整数の場合と同じように変換後に多項式を掛け合わせ、逆変換すればうまくいくようだ。

int N;

vector<valarray<ll>> FWHT(vector<valarray<ll>> P) {
	int i,j;
    for (int len = 1; 2 * len <= P.size(); len <<= 1) {
        for (int i = 0; i < P.size(); i += 2 * len) {
			FOR(j,len) {
                valarray<ll> u = P[i + j];
                valarray<ll> v = P[i + len + j];
                P[i + j] = u + v;
                P[i + len + j] = u - v;
            }
        }
    }
    
    return P;
}

vector<ll> A[32],B[32];

void solve() {
	int i,j,k,l,r,x,y; string s;
	
	cin>>N;
	vector<valarray<ll>> A(1<<N),B(1<<N);
	
	int mask;
	FOR(mask,1<<N) {
		A[mask].resize(32);
		FOR(i,32) cin>>A[mask][i];
	}
	FOR(mask,1<<N) {
		B[mask].resize(32);
		FOR(i,32) cin>>B[mask][i];
	}
	
	A=FWHT(A);
	B=FWHT(B);
	FOR(mask,1<<N) {
		valarray<ll> V(63);
		FOR(x,32) FOR(y,32) V[x+y]+=A[mask][x]*B[mask][y];
		A[mask]=V;
	}
	A=FWHT(A);
	FOR(mask,1<<N) {
		FORR(v,A[mask]) {
			v>>=N;
			cout<<abs(v)%2<<" ";
		}
		cout<<endl;
		
	}
}

まとめ

むしろ解説1を理解していない…。