[HDU6057] Kanade‘s convolution (FWT)
题面
出自HDU6057
给你两个数列
A
[
0...
2
m
−
1
]
A[0...2^m-1]
A[0...2m−1] 和
B
[
0...
2
m
−
1
]
B[0...2^m-1]
B[0...2m−1]。
请计算数列
C
[
0...
2
m
−
1
]
C[0...2^m-1]
C[0...2m−1]:
C
[
k
]
=
∑
i
            
a
n
d
            
j
=
k
A
[
i
          
x
o
r
          
j
]
∗
B
[
i
          
o
r
          
j
]
C[k]=\sum_{i\;and\;j=k}A[i\;xor\;j]*B[i\;or\;j]
C[k]=iandj=k∑A[ixorj]∗B[iorj]
你只需要输出
∑
i
=
0
2
m
−
1
C
[
i
]
∗
152
6
i
 
m
o
d
998244353
\sum_{i=0}^{2^m-1}C[i]*1526^i\!\!\mod 998244353
∑i=02m−1C[i]∗1526imod998244353
m
<
=
19
m <= 19
m<=19
0
≤
A
[
i
]
,
B
[
i
]
<
998244353
0\leq A[i],B[i]<998244353
0≤A[i],B[i]<998244353
题解
公式中的条件让我们很想用快速沃尔什变换FWT,但是该公式和FWT基本式子大相径庭,无疑给我们造成了巨大的麻烦。
我们只有两条路可走,化式子,换元。
目前公式的形态想要化式子是毫无可能性的,我们只好先换元后再做打算。
我们知道,两个数异或、按位或、按位与三个运算是有等量关系的,即:
i
          
x
o
r
          
j
=
(
i
          
o
r
          
j
)
−
(
i
          
a
n
d
          
j
)
=
(
i
          
o
r
          
j
)
         
x
o
r
         
(
i
          
a
n
d
          
j
)
i\;xor\;j=(i\;or\;j)-(i\;and\;j)=(i\;or\;j)\,xor\,(i\;and\;j)
ixorj=(iorj)−(iandj)=(iorj)xor(iandj)
有了这个关系,我们就可以消去其中一个甚至两个运算,不妨设
x
=
i
         
x
o
r
         
j
,
y
=
i
         
o
r
         
j
x=i\;xor\;j,y=i\;or\;j
x=ixorj,y=iorj,则
x
=
y
−
(
i
          
a
n
d
          
j
)
=
y
          
x
o
r
         
(
i
          
a
n
d
          
j
)
⇔
x
          
x
o
r
          
y
=
(
i
          
a
n
d
          
j
)
x
          
x
o
r
          
y
=
k
              
(
x
⊆
y
,
即
x
          
a
n
d
          
y
=
x
)
x=y-(i\;and\;j)=y\;xor\,(i\;and\;j)\\ \Leftrightarrow x\;xor\;y=(i\;and\;j)\\ x\;xor\;y=k\;\;\;(x\subseteq y,即 x\;and\;y=x)
x=y−(iandj)=yxor(iandj)⇔xxory=(iandj)xxory=k(x⊆y,即xandy=x)
化到这一步,不免心中大喜,想要直接代成
C
[
k
]
=
∑
x
          
x
o
r
          
y
=
k
A
[
x
]
∗
B
[
y
]
C[k]=\sum_{x\,xor\,y=k}A[x]*B[y]
C[k]=∑xxory=kA[x]∗B[y],并用类似子集卷积的方式限制位数来完成那热血沸腾的最后一步。
若真是这么简单,可就大错特错。这里有个坑,虽然有样例等各种数据的鼎力相助,发现这个坑对于OIer来说并不难,但当我们发现它,却着实令人倒吸一口凉气。
我们发现二元组
(
x
,
y
)
(x,y)
(x,y) 和
(
i
,
j
)
(i,j)
(i,j) 并不是一一对应!
没错,这有点令人吃惊,发现之初,甚至笔者有那么一瞬间考虑过重新化式子。这时候,冷静的思考就显得格外重要。重新化式子不是不可能,但无疑会令人士气大挫,想要再成功地化式子,除非是顶级高手,不然短时间内绝对办不到。沉吟片刻,我们自然而然地发现了其中的内在关系。
一对
(
x
,
y
)
(x,y)
(x,y) 对应的
(
i
,
j
)
(i,j)
(i,j) 不一定唯一,但它们的数量确是准确的
2
c
o
u
n
t
(
x
)
2^{count(x)}
2count(x)!
c
o
u
n
t
(
x
)
count(x)
count(x) 作为 x 中 1 的个数的定义不必多言,但为什么呢?
从定义入手,确定了 x 和 y 后,
i
         
a
n
d
         
j
i\;and\;j
iandj 就可以确定了,也就是说我们已经确定了
i
i
i 和
j
j
j 中共有的 1 是哪些,这是唯一的,那么接下来 x (
i
         
x
o
r
         
j
i\;xor\;j
ixorj)则确定了
i
i
i 和
j
j
j 中只有其一拥有的 1 的分布,这是不定的,既然这其中任意一个 1 既有可能属于
i
i
i ,又有可能属于
j
j
j ,那么总数不就自然是
2
c
o
u
n
t
(
x
)
2^{count(x)}
2count(x) 了吗?
打通了阻碍后,接下来的化式子便水到渠成:
C
[
k
]
=
∑
x
               
x
o
r
               
y
=
k
A
[
x
]
∗
B
[
y
]
∗
2
c
o
u
n
t
(
x
)
=
∑
x
               
x
o
r
               
y
=
k
(
A
[
x
]
∗
2
c
o
u
n
t
(
x
)
)
∗
B
[
y
]
(
x
⊆
y
)
\begin{matrix}C[k]=\sum_{x\,xor\,y=k}A[x]*B[y]*2^{count(x)}\\ \;\;\;\;\;\;\;\;\;\;=\sum_{x\,xor\,y=k}(A[x]*2^{count(x)})*B[y]\\ (x\subseteq y)\end{matrix}
C[k]=∑xxory=kA[x]∗B[y]∗2count(x)=∑xxory=k(A[x]∗2count(x))∗B[y](x⊆y)
 终于长舒一口气,我们可以用代码去演绎了……
(最近小说看的有点多,啰嗦了点,但思路应该比较清晰)
CODE
顺便把FWT全模板附在代码里了,可能与笔者自己的学习笔记有点出入,但无大碍。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN (1<<20|5)
#define LL long long
#define DB double
#define ENDL putchar('\n')
#define lowbit(x) (-(x) & (x))
LL read() {
	LL f=1,x=0;char s = getchar();
	while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
	while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
	return f * x;
}
char readchar() {
	char s = getchar();while(s == ' ' || s == '\n') s = getchar();
	return s;
}
const int MOD = 998244353;
const int inv2 = 998244354/2;
int n,m,i,j,s,o,k;
//----------------------FWT start-------------------------
int qm(int a,int M) {return (a>M? a-M:a);}
void DWTOR(int *s,int n) {
	for(int k = 1;k < n;k <<= 1) {
		for(int j = 0;j < n;j += (k<<1)) {
			for(int i = j;i < j+k;i ++) {
				(s[i+k] += s[i]) %= MOD;
			}
		}
	}return ;
}
void IDWTOR(int *s,int n) {
	for(int k = n/2;k > 0;k >>= 1) {
		for(int j = 0;j < n;j += (k<<1)) {
			for(int i = j;i < j+k;i ++) {
				(s[i+k] += MOD-s[i]) %= MOD;
			}
		}
	}return ;
}
void DWTAND(int *s,int n) {
	for(int k = 1;k < n;k <<= 1) {
		for(int j = 0;j < n;j += (k<<1)) {
			for(int i = j;i < j+k;i ++) {
				(s[i] += s[i+k]) %= MOD;
			}
		}
	}return ;
}
void IDWTAND(int *s,int n) {
	for(int k = n/2;k > 0;k >>= 1) {
		for(int j = 0;j < n;j += (k<<1)) {
			for(int i = j;i < j+k;i ++) {
				(s[i] += MOD-s[i+k]) %= MOD;
			}
		}
	}return ;
}
void DWTXOR(int *s,int n) {
	for(int k = 1;k < n;k <<= 1) {
		for(int j = 0;j < n;j += (k<<1)) {
			for(int i = j;i < j+k;i ++) {
				int A = s[i],B = s[i+k];
				s[i] = qm((A + B) , MOD);
				s[i+k] = qm((A +MOD- B) , MOD);
			}
		}
	}return ;
}
void IDWTXOR(int *s,int n) {
	for(int k = n/2;k > 0;k >>= 1) {
		for(int j = 0;j < n;j += (k<<1)) {
			for(int i = j;i < j+k;i ++) {
				int A = s[i],B = s[i+k];
				s[i] = qm((A + B) , MOD) *1ll*inv2 % MOD;
				s[i+k] = qm((A +MOD- B) , MOD) *1ll*inv2 % MOD;
			}
		}
	}return ;
}
//----------------------FWT end---------------------------
int ct[MAXN],po[MAXN];
int A[21][MAXN],B[21][MAXN],C[21][MAXN];
int aa[MAXN],bb[MAXN],cc[MAXN];
int main() {
	n = read();m = (1<<n);
	po[0] = 1;
	for(int i = 1;i < m;i ++) {
		ct[i] = ct[i - lowbit(i)] + 1;
		po[i] = po[i - 1] * 1526ll % MOD;
	}
	for(int i = 0;i < m;i ++) A[ct[i]][i] = read()*(1ll<<ct[i]) % MOD;
	for(int i = 0;i < m;i ++) B[ct[i]][i] = read();
	for(int i = 0;i <= n;i ++) DWTXOR(A[i],m),DWTXOR(B[i],m);
	for(int i = 0;i <= n;i ++) {
		for(int j = i;j <= n;j ++) {
			for(int k = 0;k < m;k ++) {
				(C[i][k] += A[j-i][k] *1ll* B[j][k] % MOD) %= MOD;
			}
		}
		IDWTXOR(C[i],m);
	}
	int ans = 0;
	for(int i = 0;i < m;i ++) {
		(ans += C[ct[i]][i] *1ll* po[i] % MOD) %= MOD;
	}
	printf("%d\n",ans);
	return 0;
}
[HDU6057] Kanade‘s convolution (FWT)的更多相关文章
- 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 ... 
- hdu6057 Kanade's convolution  【FWT】
		题目链接 hdu6057 题意 给出序列\(A[0...2^{m} - 1]\)和\(B[0...2^{m} - 1]\),求所有 \[C[k] = \sum\limits_{i \; and \; ... 
- 【CF850E】Random Elections(FWT)
		[CF850E]Random Elections(FWT) 题面 洛谷 CF 题解 看懂题就是一眼题了... 显然三个人是等价的,所以只需要考虑一个人赢了另外两个人就好了. 那么在赢另外两个人的过程中 ... 
- 【CF662C】Binary Table(FWT)
		[CF662C]Binary Table(FWT) 题面 洛谷 CF 翻译: 有一个\(n*m\)的表格(\(n<=20,m<=10^5\)), 每个表格里面有一个\(0/1\), 每次可 ... 
- 「WC2018」州区划分(FWT)
		「WC2018」州区划分(FWT) 我去弄了一个升级版的博客主题,比以前好看多了.感谢 @Wider 不过我有阅读模式的话不知为何 \(\text{LATEX}\) 不能用,所以我就把这个功能删掉了. ... 
- 【HDU5909】Tree Cutting(FWT)
		[HDU5909]Tree Cutting(FWT) 题面 vjudge 题目大意: 给你一棵\(n\)个节点的树,每个节点都有一个小于\(m\)的权值 定义一棵子树的权值为所有节点的异或和,问权值为 ... 
- 【UOJ#310】【UNR#2】黎明前的巧克力(FWT)
		[UOJ#310][UNR#2]黎明前的巧克力(FWT) 题面 UOJ 题解 把问题转化一下,变成有多少个异或和为\(0\)的集合,然后这个集合任意拆分就是答案,所以对于一个大小为\(s\)的集合,其 ... 
- Codeforces663E Binary Table(FWT)
		题目 Source http://codeforces.com/contest/663/problem/E Description You are given a table consisting o ... 
- Paper | Octave Convolution(OctConv)
		目录 1. 尺度空间理论(scale-space theory) 2. OctConv 3. 启发 论文:Drop an Octave: Reducing Spatial Redundancy in ... 
随机推荐
- sklearn练习1 回归
			from sklearn.svm import SVR from sklearn.pipeline import make_pipeline from sklearn.preprocessing im ... 
- 不忍了,快速下载Visual Studio Code
			更新记录 本文迁移自Panda666原博客,原发布时间:2021年5月2日. 奇怪的原因 因为一些众所周知的原因,在国内下载Visual Studio Code的速度比较慢,所以我们需要一些方法来加快 ... 
- Javaer 面试必背系列!超高频八股之三色标记法
			可达性分析可以分成两个阶段 根节点枚举 从根节点开始遍历对象图 前文提到过,在可达性分析中,第一阶段 "根节点枚举" 是必须 STW 的,不然如果分析过程中用户进程还在运行,就可能 ... 
- ESXI系列问题整理以及记录——使用Windows PowerShell中的SSH功能连接ESXI控制台
			首先进入ESXI管理页面,开启ESXI的SSH功能 接下来到位于同一局域网的Win主机上开启Powershell,如果ESXI主机的IP地址为192.168.1.77,则在Powershell中输入: ... 
- SAP JSON 格式化及解析。
			一.首选:/ui2/cl_json {'key':'value'} /ui2/cl_json=>deserialize( EXPORTING json = json CHANGING d ... 
- rhel修改系统语言
			修改系统语言的三种方式 1.yum install system-config-language //挂载本地源,然后安装 system-config-language 2. ... 
- Python实现中文字幕雨+源代码
			写在前面的一些P话: 最近浏览了很多关于用Python和Pygame实现代码雨的案例,发现很多都是没有深入讲解代码的整个实现过程,从0到1教会你制作中文文字雨. 然后在介绍的过程中,我也将深入介绍Py ... 
- idea部署项目运行没问题,但是页面404。
			解决方案: 这个位置不要添加内容. 参考:https://blog.csdn.net/hupixiong/article/details/105443606 
- CPI教程-异步接口创建及使用
			CPI教程-异步接口创建及使用 create by yi 转载请注明出处 先简单介绍一下同步接口和异步接口 什么是同步接口 同步接口的意思就是发送方发送Message后,接口方处理完成后会立刻返回执行 ... 
- 不是吧?30秒 就能学会一个python小技巧?!
			大家好鸭!我是小熊猫 很多学习Python的朋友在项目实战中会遇到不少功能实现上的问题,有些问题并不是很难的问题,或者已经有了很好的方法来解决.当然,孰能生巧,当我们代码熟练了,自然就能总结一些好用的 ... 
