1. /*
  2. HDU 6057 - Kanade's convolution [ FWT ] | 2017 Multi-University Training Contest 3
  3. 题意:
  4. 给定两个序列 A[0...2^m-1], B[0...2^m-1]
  5. 求 C[0...2^m-1] ,满足:
  6. C[k] = ∑[i&j==k] A[i^j] * B[i|j]
  7. m <= 19
  8. 分析:
  9. 看C[k]的形式与集合卷积的形式接近,故转化式子时主要向普通的集合卷积式方向靠
  10. 与三种位运算都相关的结论是 : i^j + i&j = i|j
  11. 设 x = i^j, y = i|j,则显然 k = y-x,且 k 与 x 互成关于 y 的补集,即 k = x^y
  12.  
  13. 再来关心给定(x,y),符合 x = i^j, y = i|j的(i,j)对的数目
  14. 注意到相同的位 i&j 是确定的,x = i^j 是i和j不同的位的数目,这部分谁是 0 谁是 1 不固定
  15. 故(i,j)对的数目为 2^bits(x)
  16.  
  17. 此时重写原式: C[k] = ∑ [k == x^y] [k == y-x] A[x]*2^bits(x) * B[y]
  18.  
  19. 设 A'[x] = A[x]*2^bits(x)
  20. 由于 [k == x^y],第二个条件 [k == y-x] 等价于 bits(k) == bits(y) - bits(x)
  21. C[k] = ∑ [k == x^y] [bits(k) == bits(x) - bits(y)] A'[x] * B[y]
  22.  
  23. 将 A,B,C三个数组按 bits 划分:
  24. C[bits(k)][k] = ∑ [k == x^y] A[bits(x)][x]*2^bits(x) * B[bits(y)][y]
  25.  
  26. 最后按不同的维度(bits)做 FWT即可
  27. */
  28. #include <bits/stdc++.h>
  29. using namespace std;
  30. const int MOD = 998244353;
  31. const int N = 1<<20;
  32. int rev2;
  33. long long inv( long long a , long long m)
  34. {
  35. if (a == 1) return 1;
  36. return inv(m%a, m) * (m - m/a) % m;
  37. }
  38. void FWT(int a[], int n) {
  39. for (int d = 1; d < n; d <<= 1)
  40. for (int m = d<<1, i = 0; i < n; i += m)
  41. for (int j = 0; j < d; j++)
  42. {
  43. int x = a[i+j], y = a[i+j+d];
  44. a[i+j] = (x+y) % MOD;
  45. a[i+j+d] = (x-y+MOD) % MOD;
  46. }
  47. }
  48. void UFWT(int a[], int n) {
  49. for (int d = 1; d < n; d <<= 1)
  50. for (int m = d<<1, i = 0; i < n; i += m)
  51. for (int j = 0; j < d; j++)
  52. {
  53. int x = a[i+j], y = a[i+j+d];
  54. a[i+j] = 1LL*(x+y) * rev2 % MOD;
  55. a[i+j+d] = (1LL*(x-y)*rev2 % MOD + MOD) % MOD;
  56. }
  57. }
  58. int a[20][N], b[20][N], c[20][N];
  59. int bits[N];
  60. int m, n;
  61. void init()
  62. {
  63. rev2 = inv(2, MOD);
  64. bits[0] = 0;
  65. for (int i = 1; i < N; i++) bits[i] = bits[i>>1] + (i&1);
  66. }
  67. int main()
  68. {
  69. init();
  70. scanf("%d", &m);
  71. n = 1<<m;
  72. for (int i = 0; i < n; i++)
  73. {
  74. int x; scanf("%d", &x);
  75. a[bits[i]][i] = 1LL*x * (1<<bits[i]) % MOD;
  76. }
  77. for (int i = 0; i < n; i++)
  78. {
  79. int x; scanf("%d", &x);
  80. b[bits[i]][i] = x;
  81. }
  82. for (int i = 0; i <= m; i++) FWT(a[i], n);
  83. for (int i = 0; i <= m; i++) FWT(b[i], n);
  84. for (int i = 0; i <= m; i++)
  85. for (int j = i; j <= m; j++)
  86. for (int k = 0; k < n; k++)
  87. {
  88. c[j-i][k] = (c[j-i][k] + 1LL*a[i][k] * b[j][k] % MOD) % MOD;
  89. }
  90. for (int i = 0; i <= m; i++) UFWT(c[i], n);
  91. long long ans = 0, base = 1;
  92. for (int i = 0; i < n; i++)
  93. {
  94. ans = ( ans + c[bits[i]][i] * base % MOD ) % MOD;
  95. base = base * 1526 % MOD;
  96. }
  97. printf("%lld\n", ans);
  98. }

  

HDU 6057 - Kanade's convolution | 2017 Multi-University Training Contest 3的更多相关文章

  1. HDU 6057 Kanade's convolution(FWT)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=6057 [题目大意] 有 C[k]=∑_(i&j=k)A[i^j]*B[i|j] 求 Ans ...

  2. HDU 6057 Kanade's convolution

    题目链接:HDU-6057 题意: 思路:先按照官方题解推导出下面的式子: 现在唯一的问题就是怎么解决[bit(x)-bit(y)=bit(k)]的问题. 我们定义\( F(A,k)_{i}=\lef ...

  3. hdu 6057 Kanade's convolution(子集卷积)

    题解: 然后就是接下来如何fwt 也就是如何处理bit(x) - bit(y) = bit(k)这个条件. 其实就是子集卷积. 把bit(x)和bit(y)划分成两个集合,然后就是子集卷积的形式. 这 ...

  4. HDU 6059 - Kanade's trio | 2017 Multi-University Training Contest 3

    思路来自题解(看着题解和标程瞎吉尔比划了半天) /* HDU 6059 - Kanade's trio [ 字典树 ]  |  2017 Multi-University Training Conte ...

  5. HDU 6058 - Kanade's sum | 2017 Multi-University Training Contest 3

    /* HDU 6058 - Kanade's sum [ 思维,链表 ] | 2017 Multi-University Training Contest 3 题意: 给出排列 a[N],求所有区间的 ...

  6. HDU 6162 - Ch’s gift | 2017 ZJUT Multi-University Training 9

    /* HDU 6162 - Ch’s gift [ LCA,线段树 ] | 2017 ZJUT Multi-University Training 9 题意: N节点的树,Q组询问 每次询问s,t两节 ...

  7. HDU 6058 Kanade's sum —— 2017 Multi-University Training 3

    Kanade's sum Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  8. 2017 Wuhan University Programming Contest (Online Round) Lost in WHU 矩阵快速幂 一个无向图,求从1出发到达n最多经过T条边的方法数,边可以重复经过,到达n之后不可以再离开。

    /** 题目:Lost in WHU 链接:https://oj.ejq.me/problem/26 题意:一个无向图,求从1出发到达n最多经过T条边的方法数,边可以重复经过,到达n之后不可以再离开. ...

  9. 2017 Wuhan University Programming Contest (Online Round) C. Divide by Six 分析+模拟

    /** 题目:C. Divide by Six 链接:https://oj.ejq.me/problem/24 题意:给定一个数,这个数位数达到1e5,可能存在前导0.问为了使这个数是6的倍数,且没有 ...

随机推荐

  1. SQLite进阶-14.子查询

    目录 子查询 SELECT语句中的子查询 INSERT语句中的子查询 UPDATE语句中的子查询 DELETE语句中的子查询 子查询 子查询或内部查询或嵌套查询是在另一个SQLite查询内嵌入在WHE ...

  2. npm添加代理和取消代理

    1.设置http代理 npm config set proxy=http://代理服务器地址:8080 2.取消代理 npm config delete proxy 3.npm设置淘宝镜像 npm c ...

  3. springboot集成mongoDB简易使用

    1.首先是添加Spring Data mongo的配置依赖 <dependency> <groupId>org.springframework.boot</groupId ...

  4. ubuntu下java的安装与执行

    一.安装java sudo add-apt-repository ppa:linuxuprising/java sudo apt-get update sudo apt-get install ora ...

  5. c# 金钱大写转小写工具类

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  6. HDU - 2196(树形DP)

    题目: A school bought the first computer some time ago(so this computer's id is 1). During the recent ...

  7. 【调试经验】C++和C的混合编程以及库调用

    问题背景 这两天在移植一个开源的库,偏底层的那种,所以对架构有一些依赖.源码的编译是通过Makefile来构建,怎奈公司的架构用的是CMAKE,所以就在开源的顶层和子目录分别构建了CMakeList, ...

  8. 多线程学习:win32多线程编程基本概念(转)

    一.定义: 1.进程和线程的区别 进程:是程序的执行过程,具有动态性,即运行的程序就叫进程,不运行就叫程序 ,每个进程包含一到多个线程.线程:系统中的最小执行单元,同一进程中有多个线程,线程可以共享资 ...

  9. Jobs(一)前端页面

    Java Web工程中的Intellij中Java Web工程的基本目录: 启动web工程后,显示的默认页面是index.html.需要注意的是,本来IDE自建的是index.jsp,我暂时改成了in ...

  10. antd做form表单的组件共用,利用mapPropsToFields填写默认值

    做单页应用,不管是用Vue还是React,或者其他,有一个重要的原则,就是:组件重用. 既然组件可以重用,那么当添加一个信息,和修改该信息的布局必然是一致的,这时候,最好的方法自然是利用同一个组件,在 ...