• HDU 6057 Kanade's convolution


    HDU 6057 Kanade's convolution

    $ C[k]=sum_{i ext { and } j=k} A[i xor j] * B[i ext { or } j] $

    假设 $ p = i or j, t = i xor j $ 那么有 $ t sub p $,其次显然 此时 $ i and j = p-t=p xor t $

    $ C[k] = sum_{p xor t=k} alpha(p,t)A[t]B[p] $

    $ alpha(p,t) $ 就是对于一对 $ p , t $ 有多少的 $ i,j $ 与之对应。

    对于每一位来考虑,如果这位 $ p = 1 , t = 0 $ 那么显然 $ i , j $ 在这一位都是 $ 1 $

    如果 $ p = 1 , t = 1 $ 那么这一位 可以 $ i = 1 , j = 0 $ 或者 $ i = 0 , j = 1 $

    否则如果 $ p = 0 , t = 0 $ 这一位 只能都是 $ 0 $

    所以实际上, 2 的 $ t $ 的 1 的个数次方就是 $ alpha(p,t) $

    所以式子就是 $ displaystylesum_{p xor t=k,tsub p} 2^{cnt(t)}A[t]B[p] $

    $ p xor t = k , t sub p $ 也就等价于 $ |p| - |t| = |k| , p xor t = k $ 这个可以枚举 $ |p|,|t| $ 来做,和子集卷积一样,复杂度 $ n22n $

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    using namespace std;
    #define MAXN ( 1 << 20 ) + 12
    #define P 998244353
    //#define int long long
    typedef long long ll;
    int n , inv2;
    int A[MAXN] , B[MAXN] , I[MAXN];
    int Pow( int a , int x ) {
    	int res = a , ans = 1;
    	while( x ) {
    		if( x & 1 ) ans = 1ll * ans * res % P;
    		res = 1ll * res * res % P , x >>= 1;
    	}
    	return ans;
    }
    namespace fwt {
        
        inline void FWT1(int a[], int len) {
            for (int mid = 2; mid <= len; mid <<= 1) 
                for (int i = 0; i < len; i += mid)
                    for (int j = i; j < i + (mid >> 1); j++) 
                        a[j + (mid >> 1)] += a[j] , a[j + (mid >> 1)] %= P;
        }
        
        inline void IFWT1(int a[], int len) {
            for (int mid = 2; mid <= len; mid <<= 1) 
                for (int i = 0; i < len; i += mid)
                    for (int j = i; j < i + (mid >> 1); j++) 
                        a[j + (mid >> 1)] -= a[j] , a[j + (mid >> 1)] += P , a[j + (mid >> 1)] %= P;
        }
        
        inline void FWT2(int a[], int len) {
            for (int mid = 2; mid <= len; mid <<= 1) 
                for (int i = 0; i < len; i += mid)
                    for (int j = i; j < i + (mid >> 1); j++) 
                        a[j] += a[j + (mid >> 1)];
        }
        
        inline void IFWT2(int a[], int len) {
            for (int mid = 2; mid <= len; mid <<= 1) 
                for (int i = 0; i < len; i += mid)
                    for (int j = i; j < i + (mid >> 1); j++) 
                        a[j] -= a[j + (mid >> 1)];
        }
        
        inline void FWT3(int a[], int len) {
            for (int mid = 2; mid <= len; mid <<= 1) 
                for (int i = 0; i < len; i += mid)
                    for (int j = i; j < i + (mid >> 1); j++) {
                        ll x = a[j], y = a[j + (mid >> 1)];
                        a[j] = ( x + y ) % P, a[j + (mid >> 1)] = ( x - y + P ) % P ;
                    }
        }
        
        inline void IFWT3(int a[], int len) {
            for (int mid = 2; mid <= len; mid <<= 1) 
                for (int i = 0; i < len; i += mid)
                    for (int j = i; j < i + (mid >> 1); j++) {
                        ll x = a[j], y = a[j + (mid >> 1)];
                        a[j] = ( 1ll * (x + y) % P * inv2 ) % P, a[j + (mid >> 1)] = ( 1ll * (x - y + P) % P * inv2 ) % P;
                    }
        }
    }
    
    int a[20][MAXN] , b[20][MAXN] , ans[20][MAXN] , res[MAXN];
    signed main() {
    	cin >> n;
    	inv2 = Pow( 2 , P - 2 );
    	int len = ( 1 << n );
    	for( int i = 0 ; i < len ; ++ i ) scanf("%d",&A[i]) , a[__builtin_popcount( i )][i] = 1ll * A[i] * ( 1 << ( __builtin_popcount( i ) ) ) % P;
    	for( int i = 0 ; i < len ; ++ i ) scanf("%d",&B[i]) , b[__builtin_popcount( i )][i] = B[i];
    	for( int i = 0 ; i <= n ; ++ i ) fwt::FWT3( a[i] , len ) , fwt::FWT3( b[i] , len );
    	for( int i = 0 ; i <= n ; ++ i ) { 
    		for( int j = 0 ; j <= i ; ++ j ) {
    			for( int k = 0 ; k < len ; ++ k ) 
    				( ans[j][k] += 1ll * a[i - j][k] * b[i][k] % P ) %= P; // , cout << i - j << ' ' << k << ':' << a[i - j][k] << endl;;
    		}
    	}
    	for( int i = 0 ; i <= n ; ++ i ) fwt::IFWT3( ans[i] , len );
    	for( int i = 0 ; i < len ; ++ i ) res[i] = ans[__builtin_popcount( i )][i];
    	int c = 1 , ret = 0;
    	for( int i = 0 ; i < len ; ++ i )
    		ret = ( ret + 1ll * res[i] * c % P ) % P , c = 1ll * c * 1526 % P; // , cout << res[i] << endl;
    	cout << ret << endl;
    }
    
  • 相关阅读:
    Oracle数据库配置
    匹配汉字与全角半角括号
    Linux任务调度crontab时间规则介绍
    配置文件方面的总结
    openlayers 4快速渲染管网模型数据
    openlayers 各种图层,持续更新
    简单的js定时器
    mysql client does not support authentication
    java 记录
    创建maven工程
  • 原文地址:https://www.cnblogs.com/yijan/p/hdu6057.html
Copyright © 2020-2023  润新知