CF1034E Little C Loves 3 III(神仙构造+FWT_OR卷积)

title

题目

solution

先说很神仙的结论构造:对于 a i a_i ai a i = v i ∗ 4 p o p _ c o u n t ( i ) a_i=v_i*4^{pop\_count(i)} ai=vi4pop_count(i) b b b同理
c i = ∑ j ∣ k = i a i ∗ b j c_i=\sum_{j|k=i}a_i*b_j ci=jk=iaibj,则 a n s i ≡ c i 4 p o p _ c o u n t ( i ) m o d    4 ans_i\equiv \frac{c_i}{4^{pop\_count(i)}}\mod 4 ansi4pop_count(i)cimod4

证明: p o p _ c o u n t ( i ) + p o p _ c o u n t ( j ) ≥ p o p _ c o u n t ( i ∣ j ) pop\_count(i)+pop\_count(j)\ge pop\_count(i|j) pop_count(i)+pop_count(j)pop_count(ij)
i & j = 0 i\&j=0 i&j=0,对答案将有贡献
4 p o p _ c o u n t ( i ) × 4 p o p _ c o u n t ( j ) 4 p o p _ c o u n t ( i ∣ j ) = 1 \frac{4^{pop\_count(i)}\times 4^{pop\_count(j)}}{4^{pop\_count(i|j)}}=1 4pop_count(ij)4pop_count(i)×4pop_count(j)=1
i & j ≠ 0 i\&j≠0 i&j=0,模 4 4 4 0 0 0,无贡献
4 p o p _ c o u n t ( i ) × 4 p o p _ c o u n t ( j ) 4 p o p _ c o u n t ( i ∣ j ) = 4 x , x ∈ N ∗ \frac{4^{pop\_count(i)}\times 4^{pop\_count(j)}}{4^{pop\_count(i|j)}}=4^x,x∈N^* 4pop_count(ij)4pop_count(i)×4pop_count(j)=4x,xN
构造非常巧妙,一般来说是不可能自己想得出来的;这种结论都是难知道却好证
o(╥﹏╥)o I’m so vegetable!

code

#include <cstdio>
#define int long long
#define maxn 2100000
int n, N;
int a[maxn], b[maxn], c[maxn];

void FWT_or( int *v, int opt ) {
    
    
	for( int i = 1;i < n;i <<= 1 )
		for( int j = 0;j < n;j += ( i << 1 ) )
			for( int k = 0;k < i;k ++ )
				v[j + k + i] += opt * v[j + k];
}

signed main() {
    
    
	scanf( "%d", &N );
	n = 1 << N;
	for( int i = 0;i < n;i ++ ) scanf( "%1lld", &a[i] );
	for( int i = 0;i < n;i ++ ) scanf( "%1lld", &b[i] );
	for( int i = 0;i < n;i ++ ) a[i] <<= ( __builtin_popcount( i ) << 1 );
	for( int i = 0;i < n;i ++ ) b[i] <<= ( __builtin_popcount( i ) << 1 );
	FWT_or( a, 1 ), FWT_or( b, 1 );
	for( int i = 0;i < n;i ++ ) c[i] = a[i] * b[i];
	FWT_or( c, -1 );
	for( int i = 0;i < n;i ++ ) c[i] = c[i] >> ( __builtin_popcount( i ) << 1 ) & 3;
	for( int i = 0;i < n;i ++ ) printf( "%lld", c[i] );
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Emm_Titan/article/details/115216035