• 【CF1119H】Triple


    【CF1119H】Triple

    题面

    洛谷

    题解

    有一个想法就是把每一个({a_i,b_i,c_i})写成生成函数( ext{F}_i)然后 FWT 起来,再 IFWT 回去发现这样是过不了的。
    因为有(FWT(A imes B)=FWT(A) imes FWT(B))
    所以 FWT 后所得的结果就是直接把每个 FWT 后再点积起来,即(FWT(prod ext F_k)=prod FWT( ext F_k)[i]=prod_{j=1}^n(-1)^{|a_j&i|}x+(-1)^{|b_j&i|}y+(-1)^{|c_j&i|}z),想办法求出(FWT)数组。
    因为每个项都是(x,y,z)加减起来的,但是这样子的话有(8)种结果,比较烦,考虑将每个三元组异或上(a_i),那么找(i)最终答案的项数再异或上一个(oplus_i a_i)即可,三元组就变为({0,a_ioplus b_i,a_ioplus c_i})
    那么现在我们只有(x+y+z,x+y-z,x-y+z,x-y-z),想办法将四种情况的数目求出来,设对于某个(i),四种情况的数目为(e,f,g,h),那么显然有(e+f+g+h=n)

    如果令( ext F_k[b_k]=1),其他项为(0),相当于(x=0,y=1,z=0),那么最终求出来的结果就是(y)前面的系数,即(y)系数为正减去(y)系数为负的情况,那么有(e+f-g-h=FWT(sum ext F_k)[i])(sum ext F_k)在括号里是因为(FWT(A)+FWT(B)=FWT(A+B))

    同理可以令( ext F_k[c_k]=1,a_k=b_k=0),其他项为(0),相当于(x=0,y=0,z=1),那么求的是(z)前面的系数,有(e-f+g-h=FWT(sum ext F_k)[i])

    再令( ext F_k[b_koplus c_k]=1)其他为(0),那么就是求的两个的卷积=点值点积即( ext F_k[i]=(-1)^{|b_j&i|}(-1)^{|c_j&i|}),也是同时考虑(x,y)前符号相同(-)不同,即(e-f-g+h=FWT(sum ext F_k)[i])

    (e,f,g,h)解方程解出来就好了,实现细节详见代码。

    代码

    #include <iostream> 
    #include <cstdio> 
    #include <cstdlib> 
    #include <cstring> 
    #include <cmath> 
    #include <algorithm> 
    using namespace std; 
    using LL = long long; 
    const int Mod = 998244353, inv2 = (Mod + 1) >> 1; 
    int fpow(int x, LL y) {
        int res = 1; 
        while (y) {
            if (y & 1) res = 1ll * res * x % Mod; 
            x = 1ll * x * x % Mod; 
            y >>= 1; 
        } 
        return res; 
    } 
    const int MAX_N = 1 << 17 | 1; 
    int N, K, Limit; 
    void FWT(LL p[]) { 
        for (int i = 1; i < Limit; i <<= 1) 
            for (int j = 0; j < Limit; j += i << 1) 
                for (int k = 0; k < i; k++) { 
                    LL x = p[j + k], y = p[i + j + k]; 
                    p[j + k] = x + y, p[i + j + k] = x - y; 
                } 
    }
    void IFWT(LL p[]) { 
        for (int i = 1; i < Limit; i <<= 1) 
            for (int j = 0; j < Limit; j += i << 1) 
                for (int k = 0; k < i; k++) { 
                    LL x = p[j + k] % Mod, y = p[i + j + k] % Mod; 
        		p[j + k] = 1ll * (x + y) * inv2 % Mod, p[i + j + k] = 1ll * (x - y + Mod) * inv2 % Mod; 
                } 
    } 
         
    LL F[MAX_N], G[MAX_N], H[MAX_N], A[MAX_N];
    int x, y, z; 
    int sum;
    LL s1, s2, s3, s4; 
         
    int main () { 
    #ifndef ONLINE_JUDGE 
        freopen("cpp.in", "r", stdin); 
    #endif 
        scanf("%d %d %d %d %d", &N, &K, &x, &y, &z); Limit = 1 << K; 
        for (int i = 1; i <= N; i++) { 
            int a, b, c; scanf("%d %d %d", &a, &b, &c); 
            sum ^= a, ++F[a ^ b], ++G[a ^ c], ++H[b ^ c]; 
        } 
        s1 = 1ll * x + y + z, s2 = 1ll * x + y - z, s3 = 1ll * x - y + z, s4 = 1ll * x - y - z;
        s1 %= Mod, s2 %= Mod, s3 %= Mod, s4 %= Mod; 
        FWT(F), FWT(G), FWT(H); 
        for (int i = 0; i < Limit; i++) {
            LL e = (N + F[i] + G[i] + H[i]) >> 2; 
            LL f = (N + F[i] - 2 * e) >> 1; 
            LL g = (N + G[i] - 2 * e) >> 1;
            LL h = (N + H[i] - 2 * e) >> 1; 
            A[i] = 1ll * fpow(s1, e) * fpow(s2, f) % Mod * fpow(s3, g) % Mod * fpow(s4, h) % Mod; 
        } 
        IFWT(A); 
        for (int i = 0; i < Limit; i++) printf("%I64d ", (A[i ^ sum] + Mod) % Mod); 
        putchar('
    '); 
        return 0; 
    } 
    
  • 相关阅读:
    一月十三号学习日报
    一月十四号学习日报
    一月六号学习日报
    ARP欺骗
    一月十一号学习日报
    vscode文件名重叠
    vue : 无法加载文件 C:Users1111111AppDataRoaming pmvue.ps1,因为在此系统禁止运行脚本
    成绩录入和查询
    node搭建服务器
    class和id的区别
  • 原文地址:https://www.cnblogs.com/heyujun/p/13296731.html
Copyright © 2020-2023  润新知