zoukankan      html  css  js  c++  java
  • hdu 6057 Kanade's convolution(子集卷积)

    题解:

    然后就是接下来如何fwt

    也就是如何处理bit(x) - bit(y) = bit(k)这个条件。

    其实就是子集卷积。

    把bit(x)和bit(y)划分成两个集合,然后就是子集卷积的形式。

    这里设两个新的数组 A[bit(y)][y], B[bit(x)][x],代表拆出来的相应数组

    然后对这两个数组做fwt,得到其点值表示,然后直接在外层枚举x和y的大小然后做卷积即可。

    这样说可能很抽象,其实贴出代码就很清楚了

    #include <iostream>
    #include <vector>
    #include <cstdio>
    using namespace std;
    const int MOD = 998244353;
    typedef long long LL;
    LL mypow(LL a, LL b){
        LL ans = 1; for(; b; b >>= 1) { if(b&1) (ans *= a) %= MOD; (a *= a) %= MOD; } return ans;
    }
    LL I2 = mypow(2, MOD-2);
    const int maxn = (1<<19) + 100;
    LL a[maxn], b[maxn], A[21][maxn*4], B[21][maxn*4], C[21][maxn*4];
    vector<int> Bit[21];
    int m;
    
    class FWT{
    public:
        void fwt(LL *a, int n){
            for(int d = 1; d < n; d <<= 1){
                for(int m = d<<1, i = 0; i < n; i += m){
                    for(int j = 0; j < d; j++){
                        LL x = a[i+j], y = a[i+j+d];
                        a[i+j] = x+y; if(a[i+j] >= MOD) a[i+j] -= MOD;
                        a[i+j+d] = x-y;   if(a[i+j+d] < 0) a[i+j+d] += MOD;
                    }
                }
            }
        }
        void ufwt(LL *a, int n){
            for(int d = 1; d < n; d <<= 1){
                for(int m = d<<1, i = 0; i < n; i += m){
                    for(int j = 0; j < d; j++){
                        LL x = a[i+j], y = a[i+j+d];
                        a[i+j] = (x+y)*I2%MOD; a[i+j+d] = (x-y+MOD)*I2%MOD;
                    }
                }
            }
        }
        void work(LL *a, LL *b, int n){
            fwt(a, n);
            fwt(b, n);
            for(int i = 0; i < n; i++) a[i] *= b[i];
            ufwt(a, n);
        }
    }myfwt;
    
    int bit(int x){
        int ans = 0;
        for(int i = 0; i < 19; i++)
            ans += ((x&(1<<i)) > 0);
        return ans;
    }
    
    int main()
    {
        for(int i = 0; i < (1<<19); i++) Bit[bit(i)].push_back(i);
        cin>>m;
        for(int i = 0; i < (1<<m); i++) scanf("%d", &a[i]);
        for(int i = 0; i < (1<<m); i++) scanf("%d", &b[i]);
        int L = (1<<m);
        for(int i = 0; i <= m; i++){
            for(auto x : Bit[i]){
                if(x >= L) break;
                A[i][x] = (a[x]*(1<<i))%MOD;
                B[i][x] = b[x];
            }
            myfwt.fwt(A[i], L);
            myfwt.fwt(B[i], L);
        }
        for(int x = 0; x <= m; x++)
            for(int y = 0; y <= x; y++)
                for(int i = 0; i < L; i++)
                    (C[x-y][i] += A[y][i]*B[x][i]) %= MOD;
        for(int i = 0; i <= m; i++) myfwt.ufwt(C[i], L);
        LL ans = 0, t = 1;
        for(int i = 0; i < (1<<m); i++){
            (ans += C[bit(i)][i]*t) %= MOD;
            (t *= 1526) %= MOD;
        }
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    给西安市网民的一封信
    西客集推出西安我家的功能了
    西客集又增加新功能了
    为者常成,行者常至
    kvm虚拟机磁盘&文件系统扩容流程
    Git常用命令大全
    Linux下Nexus的部署教程
    sonatype nexus简介(转)
    curl时加参数o或重定向符号>>将结果输出不到文件里怎么办?
    吞吐量(TPS)、QPS、并发数、响应时间(RT)概念
  • 原文地址:https://www.cnblogs.com/Saurus/p/7374604.html
Copyright © 2011-2022 走看看