题意:

给出一个数组a,要求把a数组选出两个不相交且不同时为空的子集,满足两个集合中数字的异或和相等。

题解:

考虑dp[i][j]dp[i][j]dp[i][j]表示考虑前iii个数字,且现在两个集合数字的异或和为j" role="presentation" style="position: relative;">jjj时的方案数。转移方程为:

dp[i][j]=dp[i−1][j]+2∗dp[i−1][jxora[i]]dp[i][j]=dp[i−1][j]+2∗dp[i−1][jxora[i]]

dp[i][j] = dp[i-1][j] + 2*dp[i-1][j \;xor\; a[i]]
然后得到了一个 n∗217n∗217n*2^{17}的算法。
接下来考虑如何加速这个dp过程。
设 b[i]b[i]b[i]是一个数组, b[i][0]=1b[i][0]=1b[i][0]=1, b[i][a[i]]=2b[i][a[i]]=2b[i][a[i]] = 2,其他的 b[i][j]=0b[i][j]=0b[i][j] =0,则

dp[i][j]=1∗dp[i−1][jxor0]+2∗dp[i−1][jxora[i]]=∑k=0Ndp[i−1][jxork]∗b[i][k](3)(4)(3)dp[i][j]=1∗dp[i−1][jxor0]+2∗dp[i−1][jxora[i]](4)=∑k=0Ndp[i−1][jxork]∗b[i][k]

\begin{align} dp[i][j] &= 1 * dp[i-1][j \; xor \; 0] + 2 * dp[i-1][j \; xor \; a[i]] \\ &=\sum_{k = 0}^{N} dp[i-1][j \; xor \; k] * b[i][k] \end{align}
于是我们把转移方程转化为两个数组作异或卷积。即 dp[i]=dp[i−1]∗b[i]dp[i]=dp[i−1]∗b[i]dp[i] = dp[i-1] * b[i]这里的乘法为异或卷积。
目前,我们得到了一个更不优秀的 n∗217∗17n∗217∗17n*2^{17}*17复杂度的算法。
但是考虑整个算法,我们要求的答案是

dp[n]=dp[0]∗b[1]∗b[2]∗...∗b[n]dp[n]=dp[0]∗b[1]∗b[2]∗...∗b[n]

dp[n] = dp[0]*b[1]*b[2]*...*b[n]
其中 dp[0]dp[0]dp[0]数组只有 dp[0][0]=1dp[0][0]=1dp[0][0] = 1,其他 dp[0][j]=0dp[0][j]=0dp[0][j] = 0。
答案就是 dp[n][0]−1dp[n][0]−1dp[n][0] - 1,这个 −1−1-1是因为存在一种两个集合都是空集的方案,要去掉。
问题就变成了我们要求连续n个b数组的异或卷积。而每个b数组都有共同的性质: b[i][0]=1b[i][0]=1b[i][0] = 1,且只有一个位置为2,其他位置都是0。
考虑fwt变换,即 FWT(b[i])FWT(b[i])FWT(b[i])数组中

FWT(b[i])[j]=∑kb[i][k]∗(−1)[kandj]FWT(b[i])[j]=∑kb[i][k]∗(−1)[kandj]

FWT(b[i])[j] = \sum_{k}{b[i][k]*(-1)^{[k\;and\;j]}}
其中[x] 表示x的二进制表示中1的个数。
因此我们显然的发现 b[i][j]=3orb[i][j]=−1b[i][j]=3orb[i][j]=−1b[i][j] = 3 \; or\;b[i][j] = -1,因为b[i]中仅有两个非零值: b[i][0]=1,b[i][a[i]]=2b[i][0]=1,b[i][a[i]]=2b[i][0] =1,b[i][a[i]] = 2带入上面的定义式就可以发现这一点。
那么继续考虑我们做异或卷积的过程是将每个 b[i]b[i]b[i]数组变换成 FWT(b[i])FWT(b[i])FWT(b[i]),然后对应位置乘起来,再做一次 IFWTIFWTIFWT即可。
于是我们知道在做对应位置相乘的时候,我们实质上是将若干个3和-1乘起来。于是我们就是要计算每个位置的 cnt3cnt3cnt3和 cnt1cnt1cnt1。显然

cnt3+cnt1=ncnt3+cnt1=n

cnt3+cnt1 = n
进而我们只需要计算

sum[k]=∑inFWT(b[i][k])sum[k]=∑inFWT(b[i][k])

sum[k] = \sum_{i}^{n}{FWT(b[i][k])}
然后,由方程

3∗cnt3−cnt1=3∗cnt3−(n−cnt3)=sum[k]3∗cnt3−cnt1=3∗cnt3−(n−cnt3)=sum[k]

3*cnt3 - cnt1 = 3*cnt3-(n - cnt3) = sum[k]
就可以直接解出

cnt3=(sum[k]+n)/4,cnt1=n−cnt3cnt3=(sum[k]+n)/4,cnt1=n−cnt3

cnt3 = (sum[k] + n) /4 , cnt1 = n - cnt3
然后便得到了整个 FWT(b[1])∗FWT(b[2])∗....∗FWT(b[n])FWT(b[1])∗FWT(b[2])∗....∗FWT(b[n])FWT(b[1])*FWT(b[2])* .... *FWT(b[n])的每一项。这里的乘法为对应项相乘。
那么我们在来看一下我们要求的这个

sum[k]=∑inFWT(b[i][k])=n+2∗∑j(−1)[a[j]andk]sum[k]=∑inFWT(b[i][k])=n+2∗∑j(−1)[a[j]andk]

sum[k] = \sum_{i}^{n}{FWT(b[i][k])} = n + 2*\sum_{j}{(-1)^{[a[j] \; and\; k]}}
再仔细的看一下

∑j(−1)[a[j]andk]∑j(−1)[a[j]andk]

\sum_{j}{(-1)^{[a[j] \; and\; k]}}
没错。。。我们设A数组,A[i] = 数字 i 在a数组中出现的次数
然后有

sum=FWT(A)sum=FWT(A)

sum = FWT(A)
分析完了之后,感觉整个人都智障了不少。。。我们拿着A做一次FWT,然后对于每个位置算出cnt3,cnt1,直接快速幂算好每个位置的值,然后IFWT回去。。。。
复杂度 217∗17217∗172^{17}*17

Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1048576;;
const int MOD = 998244353;
const int INV2 = (MOD+1)>>1;
const int INV4 = 1LL*INV2*INV2%MOD;
int a[N];
int bas[N+1];
int n;
void FWT(int *a,int n,int r){for (int i=1;i<n;i<<=1){for (int j=0;j<n;j+=(i<<1)){for (int k =0;k<i;k++){int x = a[j+k];int y = a[j+k+i];if (r){a[j+k] = (x+y)%MOD;a[j+k+i] = (x-y+MOD)%MOD;}else{a[j+k] = 1LL*(x+y)*INV2%MOD;a[j+k+i] = 1LL*(x-y+MOD)*INV2%MOD;}}}}
}int main(){scanf("%d",&n);for (int i=1;i<=n;i++){int x;scanf("%d",&x);a[x]++;}bas[0] = 1;for (int i=1;i<=N;i++){bas[i] = 3LL*bas[i-1]%MOD;}FWT(a,N,1);for(int i=0;i<N;i++){a[i] = (n+2*a[i])%MOD;int cnt3 = 1LL*(a[i]+n)%MOD*INV4%MOD;int cnt1 = n-cnt3;a[i] = bas[cnt3];if (cnt1&1){a[i] = MOD-a[i];}}FWT(a,N,0);printf("%d\n",(a[0]+MOD-1)%MOD);return 0;
}

UOJ#310 【UNR #2】黎明前的巧克力:FWT相关推荐

  1. UOJ #310 黎明前的巧克力 (FWT)

    题目传送门 题目大意:给你一个序列,定义一个子序列的权值表示子序列中元素的异或和,现在让你选出两个互不相交的子序列,求选出的这两个子序列权值相等的方案数,$n,a_{i}\leq 10^{6}$ 这是 ...

  2. [UNR#2]黎明前的巧克力

    题目 传送门 to UOJ 题意概要 在给出的 nnn 个自然数中,选出两个集合,其下标不相交(一个元素至多属于一个集合),且两个集合至少有一个非空,使得两个集合内的数字的异或和相等.问方案数,对 9 ...

  3. UOJ310 黎明前的巧克力 FWT

    传送门 我们要求的是\([x^0]\prod\limits_{i=1}^n (2x^{a_i}+1)\),其中乘积定义为集合对称差卷积. 这个直接做复杂度太高了,考虑优化.注意到在FWT之后,每一个序 ...

  4. [FWT] UOJ #310. 【UNR #2】黎明前的巧克力

    [uoj#310][UNR #2]黎明前的巧克力 FWT - GXZlegend - 博客园 f[i][xor],考虑优化暴力,暴力就是FWT xor一个多项式 整体处理 (以下FWT代表第一步) F ...

  5. UOJ#310. 【UNR #2】黎明前的巧克力

    初见安~这里是传送门:uoj#310. [UNR #2]黎明前的巧克力 题解 这题挺降智的--考虑如果能选出来一个集合使之异或和为0,那么这个集合划分成任意两个集合一定都满足条件. 容易想到形如背包, ...

  6. UNR2 黎明前的巧克力

    C 黎明前的巧克力 [* hard] 给定数列 (a),长度为 (n),保证 (n,a_ile 10^6),求有多少种方案选出两个集合 (A,B) 使得两个集合的异或和相同,不能均为空集,答案对 (9 ...

  7. UOJ#310.【UNR #2】黎明前的巧克力(FWT)

    题意 给出 \(n\) 个数 \(\{a_1, \cdots, a_n\}\),从中选出两个互不相交的集合(不能都为空),使得第一个集合与第二个集合内的数的异或和相等,求总方案数 \(\bmod 99 ...

  8. C. 【UNR #2】黎明前的巧克力

    题意: Evan 和 Lyra 都是聪明可爱的孩子,两年前,Evan 开始为一个被称为UOJ的神秘的OI组织工作,在 Evan 与其他小伙伴的努力下,UOJ不仅成了OI界原创比赛的典范,更是因UR这一 ...

  9. UOJ#310-[UNR #2]黎明前的巧克力【FWT】

    1# 正题 题目链接:https://uoj.ac/problem/310 题目大意 给出一个长度为nnn的序列,求有多少种方案找出两个集合S,TS,TS,T使得这两个集合的异或和相等. 1≤n≤10 ...

最新文章

  1. Linux ping 使用教程,linux ping命令的几个简单使用方法
  2. ICS SIP Call移植
  3. LeetCode - Convert Sorted Array to Binary Search Tree
  4. [ASP.NET 控件实作 Day12] 继承 TBActiveX 重新改写 TBMediaPlayer 控件
  5. java外卖系统源码_JAVAWEB校园订餐系统项目源码 一个外卖点餐系统 - 下载 - 搜珍网...
  6. 你敲键盘的声音,出卖了你 | 附开源代码
  7. Ubuntu 12.04下jdk的安装与配置
  8. php ayyay,在PHP中使用Redis
  9. CoppeliaSim用户手册中文翻译版(一)
  10. 《代码整洁之道》阅读分享
  11. Excel插件:方方格子
  12. 项目经理必须知道什么是PERT网络分析(计划评审技术)
  13. 计算机网各管理员技能鉴定,计算机网络管理员国家职业技能鉴定考核指导
  14. 【网络】路由器集成锐捷认证
  15. Microsoft Office Word 2007 转换为 Microsoft Office Word 2003兼容方法
  16. 【1383】手机短号(多实例测试)
  17. 乐观锁和悲观锁的简单实现
  18. 微投抖的1080_抖出来的算真4K吗?DLP XPR抖动原理及效果详解
  19. mysql创建零件供应商表_● 建立一个供应商、零件数据库。其中“供应商”表 S(Sno,Sname,Zip,City)分别表示: 供应商代码、 供应 - 赏学吧...
  20. POJ1830开关问题

热门文章

  1. java菜鸟2:java指令
  2. 【电路理论】1-10 两类约束 KVL、KCL方程的独立性
  3. 人人都能成为闪电网络节点:第6章安装lnd
  4. FL Studio音乐编曲入门教程
  5. synchronized同步锁原理详解
  6. Java标识符的命名规则有哪些
  7. React学习笔记(八)--- HooK
  8. Tomcat部署war程序
  9. CHARINDEX函数
  10. 身体打来的电话,你一定要接!