[UNR # 2] predawn chocolate (combinatorics) (generating function) (FWT)

Portal

Meaning of the questions: find two sets to make them the same or different values, ask a few programs

XOR consider those statistics together as a collection, a division of any such collection is legal 0

A size S |S| contribution collection is 2 S 2^{|S|}

We consider the generating function and then on F W T FWT

get ( 2 x a i + 1 ) \prod(2*x^{a_i}+1) After i f w t ifwt back, first 0 0 value of the item is the answer

If I do find it again for each row f w t fwt too wasteful

We can not do it all together?

consider f w t fwt process, 1 1 all locations contribute, 2 2 There are a number of position 2 -2 contribution, some 2 2 contribution, the final value must be 1 , 3 -1,3

We need to know now is the transformation of an exhausted \prod , which was found only need to know the number 1 and 3

Notice f w t fwt is equal and the f w t fwt , all together to do it again f w t fwt can be solved number

Very clever, one is a direct write f w t fwt in the form of a function generating
two are put together to make an all f w t fwt , rather than doing a a

#include<bits/stdc++.h>
#define cs const
using namespace std;
cs int N = 1e6 + 5, M = 1 << 21 | 5;
cs int Mod = 998244353, inv2 = (Mod+1)/2;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
void Mul(int &a, int b){ a = mul(a, b); }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
int ksm(int a, int b){ int ans = 1; for(;b;b>>=1,a=mul(a,a)) if(b&1) ans = mul(ans, a); return ans;}
cs int inv4 = mul(inv2, inv2);
int n, a[M], pw[N], MAX, deg; 
void FWT(int *a, int typ){
	for(int i = 1; i < deg; i <<= 1)
	for(int j = 0; j < deg; j += (i<<1))
	for(int k = 0; k < i; k++){
		int x = a[k + j], y = a[k + j + i];
		a[k + j] = add(x, y); a[k + j + i] = dec(x, y);
		if(typ == -1) Mul(a[k + j], inv2), Mul(a[k + j + i], inv2);
	}
}
int main(){
	scanf("%d", &n); a[0] = n;
	for(int i = 1; i <= n; i++){ int x; scanf("%d", &x); MAX = max(MAX, x); a[x] += 2; }
	pw[0] = 1; for(int i = 1; i <= n; i++) pw[i] = mul(pw[i-1], 3);
	deg = 1; while(deg <= MAX) deg <<= 1;
	FWT(a, 1);
	for(int i = 0; i < deg; i++){
		int ct3 = mul(add(a[i], n), inv4), ct1 = n - ct3;
		a[i] = (ct1&1) ? dec(0,pw[ct3]) : pw[ct3]; 
	}
	FWT(a, -1); cout << dec(a[0], 1); return 0;
}
Published 610 original articles · won praise 94 · views 50000 +

Guess you like

Origin blog.csdn.net/sslz_fsy/article/details/103427962