羅区P4717 [テンプレート]高速ウォルシュ変換(FWT)

まあ式に直接与えられます:

またはコンボリューション:

$ 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を返します。  
}

  

おすすめ

転載: www.cnblogs.com/guangheli/p/12165061.html