[UOJ310][UNR #2]黎明前的巧克力
description
给你\(n\)个数,求从中选出两个交集为空的非空集合异或和相等的方案数模\(998244353\)。
sol
其实也就是选出一个集合满足异或和为\(0\),然后把它分成两半。
利用生成函数那套理论,就是对于每个\(a_i\),构造一个多项式\(b_i\),其中\(b_0=1,b_{a_i}=2\),然后把这\(n\)个\(b\)做集合异或卷积。这样我们就得到了一个优秀的\(O(na_i\log a_i)\)的做法辣(雾)。
我们考虑一下\(b_0=1,b_{a_i}=2\)的这个\(b\)做一次\(FWT\)后会发生什么。
打表发现,\(b_0=1\)会使得每个位置\(+1\),\(b_{a_i}=2\)会使得某些位置\(+2\),某些位置\(-2\)。所以最终变换出来的序列里只有\(3\)和\(-1\)。
我们能不能手动构造一下这若干个\(b\)的积呢?显然是可以的。我们只需要知道每一个位置上\(3\)的个数就行了(因为不是\(3\)就是\(-1\),知道了\(3\)的个数也就确定了\(-1\)的个数)。
对于每个\(a_i\),在\(b_{a_i}\)的地方加个\(1\),然后把这个\(b\)\(FWT\)一下,得到的就是每一个位置上\(3\)的个数减去\(-1\)的个数。
所以就可以方便地构造出乘积然后\(FWT\)回去了。
code
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 1<<20;
const int mod = 998244353;
int n,mx,len=1,a[N],b[N];
int fastpow(int a,int b){
int res=1;
while(b){if(b&1)res=1ll*res*a%mod;a=1ll*a*a%mod;b>>=1;}
return res;
}
void fwt(int *P,int opt){
for (int i=1;i<len;i<<=1)
for (int p=i<<1,j=0;j<len;j+=p)
for (int k=0;k<i;++k){
int x=P[j+k],y=P[j+k+i];
P[j+k]=1ll*(x+y)*opt%mod;
P[j+k+i]=1ll*(x-y+mod)*opt%mod;
}
}
int main(){
n=gi();int inv2=(mod+1)/2;
for (int i=1,x;i<=n;++i)
x=gi(),++a[x],mx=max(mx,x);
while (len<=mx) len<<=1;
fwt(a,1);
for (int i=0;i<len;++i){
int x=1ll*(a[i]+n)*inv2%mod;
a[i]=fastpow(3,x);if((n-x)&1)a[i]=mod-a[i];
}
fwt(a,inv2);
printf("%d\n",(a[0]-1+mod)%mod);
return 0;
}
[UOJ310][UNR #2]黎明前的巧克力的更多相关文章
- 【uoj#310】[UNR #2]黎明前的巧克力 FWT
题目描述 给出 $n$ 个数,从中选出两个互不相交的集合,使得第一个集合与第二个集合内的数的异或和相等.求总方案数. 输入 第一行一个正整数 $n$ ,表示巧克力的个数.第二行 $n$ 个整数 $a_ ...
- [UOJ UNR#2 黎明前的巧克力]
来自FallDream的博客,未经允许,请勿转载,谢谢. 传送门 很奇妙的一道题 首先不难发现一个暴力做法,就是f[i]表示异或和为i的答案数,每次FWT上一个F数组,其中F[0]=1,F[ai]=2 ...
- [FWT] UOJ #310. 【UNR #2】黎明前的巧克力
[uoj#310][UNR #2]黎明前的巧克力 FWT - GXZlegend - 博客园 f[i][xor],考虑优化暴力,暴力就是FWT xor一个多项式 整体处理 (以下FWT代表第一步) F ...
- uoj310【UNR #2】黎明前的巧克力(FWT)
uoj310[UNR #2]黎明前的巧克力(FWT) uoj 题解时间 对非零项极少的FWT的优化. 首先有个十分好想的DP: $ f[i][j] $ 表示考虑了前 $ i $ 个且异或和为 $ j ...
- 【UOJ#310】【UNR#2】黎明前的巧克力(FWT)
[UOJ#310][UNR#2]黎明前的巧克力(FWT) 题面 UOJ 题解 把问题转化一下,变成有多少个异或和为\(0\)的集合,然后这个集合任意拆分就是答案,所以对于一个大小为\(s\)的集合,其 ...
- 「UNR#2」黎明前的巧克力
「UNR#2」黎明前的巧克力 解题思路 考虑一个子集 \(S\) 的异或和如果为 \(0\) 那么贡献为 \(2^{|S|}\) ,不难列出生产函数的式子,这里的卷积是异或卷积. \[ [x^0]\p ...
- 【UNR #2】黎明前的巧克力 解题报告
[UNR #2]黎明前的巧克力 首先可以发现,等价于求 xor 和为 \(0\) 的集合个数,每个集合的划分方案数为 \(2^{|S|}\) ,其中 \(|S|\) 为集合的大小 然后可以得到一个朴素 ...
- UOJ #310 黎明前的巧克力 FWT dp
LINK:黎明前的巧克力 我发现 很多难的FWT的题 都和方程有关. 上次那个西行寺无余涅槃 也是各种解方程...(不过这个题至今还未理解. 考虑dp 容易想到f[i][j][k]表示 第一个人得到巧 ...
- UOJ310. 【UNR #2】黎明前的巧克力 [FWT]
UOJ 思路 显然可以转化一下,变成统计异或起来等于0的集合个数,这样一个集合的贡献是\(2^{|S|}\). 考虑朴素的\(dp_{i,j}\)表示前\(i\)个数凑出了\(j\)的方案数,发现这其 ...
随机推荐
- PostgreSQL pg_hba.conf 文件简析
作者:高张远瞩(HiLoveS) 博客:http://www.cnblogs.com/hiloves/ 转载请保留该信息 最近试用PostgreSQL 9.04,将pg_hba.conf配置的一些心得 ...
- 【Linux】使用awk批量杀进程
pkill 杀一个用户的所有进程 pkill -u bingo 批量杀进程 使用ps -ef|grep aaa 查出相关进程 使用grep -v grep 过滤掉grep本身产生的进程 使用awk 打 ...
- Ubuntu 14.04配置虚拟主机
虚拟主机常用于在一个单独的IP地址上提供多个域名的网站服务.如果有人想在单个VPS的单个IP地址运行多个网站,这是非常有用的.在这个教程中,让我告诉你如何设置在Ubuntu 14.04 LTS的Apa ...
- vim 正则 捕获
在正规表达式中使用 \( 和 \) 符号括起正规表达式,即可在后面使用\1 \2等变量来访问捕获的内容. 将捕获内容前后交换,如下: :s/\(\haha\)\(hehe\)/\\/
- Mysql5.7基于日志转为基于事务主从复制
将基于日志的复制变更为基于事务的复制 mysql版本要高于5.7.6 gtid_mode要设为off 处理步骤 详细步骤 1.查看主从mysql版本是否高于5.7.6 show variables l ...
- C# 获取命名空间对应的程序集位置
由于同名命名空间会被多个程序集使用,C#没有提供直接的方法(对象浏览器也不行)通过命名空间获得程序集位置,这样就不方便找到那些引用文件时什么. 那么可以在立即窗口,中断某个代码的时候,去查询类所在程序 ...
- poj-3046-dp
Ant Counting Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6829 Accepted: 2514 Desc ...
- Linux操作系统简介
一:Linux系统概述 1.常见操作系统 - 服务端操作系统 : linux.unix.windows server - 单机操作系统 : windows(dos .ucdos.win95.win98 ...
- 【转】ubuntu下如何将笔记本自带的键盘关闭
想必大家都经历过这样的情况:在使用usb接口的外接键盘的时候,很容易按到笔记本自带的键盘,从而导致输入错误.尤其是你将外接键盘放在笔记本键盘上面的时候.怎么解决这个问题呢? 搜索之后,找到了答案.注意 ...
- 求小于等于k长度的最大区间和
题意 给出一个序列,求长度小于等于k的最大区间和并输出起点和终点 1<=n<=100000 1<=k<=n 题解:先算出前缀和,利用单调队列的性质,在单调队列中存储sum[ ...