zoukankan      html  css  js  c++  java
  • HDU-6057 Kanade's convolution

    题面

    Description

    Give you two arrays (A[0..2^m-1]) and (B[0..2^m-1]).

    Please calculate array (C[0..2^m-1])

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

    You just need to print (sum_{i=0}^{2^m-1}C[i]*1526^i ~mod~998244353)

    (m<=19)

    (0leq A[i],B[i]< 998244353)

    Input

    There is only one test case.

    The first line consists of one integer (m).

    The second line consists of (2^m) integers (A[0..2^m-1])

    The third line consists of (2^m) integers (B[0..2^m-1])

    Output

    Output only one integer means the answer.

    Sample Input

    2
    1 2 3 4
    5 6 7 8
    

    Sample Output

    568535691
    

    题意

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

    计算上式

    题解

    我在做这题的时候没太有思路,去搜了题解,有一篇题解感觉说的很好

    https://www.cnblogs.com/Tiw-Air-OAO/p/10274225.html

    这种题,推式子显然不是我这种非专业数学选手掌握的,那么怎样提高自己做出这种题目的概率呢?

    打表大概是一个很好的办法,这篇题解里也是这样入手的

    ~ (1) (2) (3) (4)
    i 0 0 1 1
    j 0 1 0 1
    i xor j 0 1 1 0
    i or j 0 1 1 1
    i and j 0 0 0 1

    我们令(a = i~xor~ j,b=i~or~j, c=i~and~j)

    我们可以发现,显然,当异或值某一位为1的时候,或该位上必定为1,此时,i和j是该位上是可以有两种情况的,01或者10,而异或值为0,或值为1,和异或值为1,或值为0,i和j都是唯一确定的,也就是说我们可以根据异或值按位1的数量来判断i和j能够产生a和b的(i,j)数目,也就是(2^{bit(a)}),其中bit(a)表示a中1的数量

    这样,我们一开始的时候,就把a(x)乘上(2^{bit(a)}),这样我们就可以不考虑原来的i和j而直接考虑a,b了

    仔细观察,(a oplus b = c)

    但是这个是有条件的,上面也说了,异或某一位是1,或该位上必定是1,也就是说,(a~and~b=a),这个条件我们不好控制,但我们可以用之前的bit数组来控制,(a~and~b=a Leftrightarrow bit(b)-bit(a) = bit(c))

    我们可以把a数组中bit(i)=k的数放在(A[bit[i]][i]),b同理,然后做fwt得到c[i-j],然后只保留c中(C[bit[i]][i])的数即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod = 998244353;
    const ll inv2 = (mod + 1) >> 1;
    
    void fwt_xor(ll a[], int len, int op) {
        for (int h = 2; h <= len; h <<= 1) {
            for (int j = 0; j < len; j += h) {
                for (int k = j; k < j + h / 2; k++) {
                    ll u = a[k], t = a[k + h / 2];
                    a[k] = (u + t) % mod;
                    a[k + h / 2] = (u - t + mod) % mod;
                    if (op == -1) {
                        a[k] = a[k] * inv2 % mod;
                        a[k + h / 2] = a[k + h / 2] * inv2 % mod;
                    }
                }
            }
        }
    }
    
    const ll N = 1 << 20;
    ll a[N], b[N];
    int bit[N];
    ll A[21][N], B[21][N];
    ll C[21][N];
    int main() {
        int m;
        scanf("%d", &m);
        int n = (1 << m);
        for (int i = 0; i < n; i++) {
            scanf("%lld", &a[i]);
        }
        for (int i = 0; i < n; i++) {
            scanf("%lld", &b[i]);
        }
        for (int i = 0; i < n; i++) {
            bit[i] = 0;
            int x = i;
            while (x) {
                if (x & 1) bit[i]++;
                x >>= 1;
            }
        }
        for (int i = 0; i < n; i++) {
            A[bit[i]][i] = a[i] * (1ll << bit[i]) % mod;
            B[bit[i]][i] = b[i];
        }
        for (int i = 0; i <= m; i++) {
            fwt_xor(A[i], n, 1);
            fwt_xor(B[i], n, 1);
        }
        for (int i = 0; i <= m; i++) {
            for (int j = 0; j <= i; j++) {
                for (int k = 0; k < n; k++) {
                    C[i - j][k] = (C[i - j][k] + A[j][k] * B[i][k] % mod) % mod;
                }
            }
        }
        for (int i = 0; i <= m; i++) {
            fwt_xor(C[i], n, -1);
        }
        ll now = 1;
        ll ans = 0;
        for (int i = 0; i < n; i++) {
            ans = (ans + C[bit[i]][i] * now % mod) % mod;
            now = now * 1526 % mod;
        }
        printf("%lld
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    android视频录制
    UIWebView 缓存
    (Detected problems with API compatibility(visit g.co/dev/appcompat for more info)
    二、为什么要安装jdk?
    一、java为什么叫java?
    jstl标签
    J2EE(八)——myeclipse开发servlet
    J2EE(七)——myeclipse开发servlet
    J2EE(六)——servlet生命周期
    J2EE(五)——servlet初识
  • 原文地址:https://www.cnblogs.com/artoriax/p/12241760.html
Copyright © 2011-2022 走看看