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

首先可以发现,等价于求 xor 和为 \(0\) 的集合个数,每个集合的划分方案数为 \(2^{|S|}\) ,其中 \(|S|\) 为集合的大小

然后可以得到一个朴素 dp ,令 \(dp_{i,j}\) 代表前 \(i\) 个数字 xor 和为 \(j\) 的集合个数

显然转移为

\[dp_{i,j}=dp_{i-1,j}+2dp_{i-1,j \ xor \ a_i}
\]

从 FWT 的角度考虑,转移其实就是每次卷上 b

\[b_{0}=1,b_{a[i]}=2
\]

考虑异或 FWT 的正变换

\[b'_i=\sum_{j} b_j(-1)^{popcount(i\&j)}
\]

我们可以发现, \(b\) 经过正变换后,每个位置的值要么是 \(3\) ,要么是 \(-1\)

我们把每个 \(b\) 的正变换乘在一起,实际上就是把若干个 \(3\) 和 \(-1\) 乘在一起,我们只需要球出每个位置有多少个 \(3\) 就可以了

显然有 \(cnt_3+cnt_1=n\)

然后我们有 和的 FWT 等于 FWT 的和

于是我们把原本所有的 \(b\) 加在一起做一遍 FWT 得到 \(c\),就可以得到第二个方程,对第 \(i\) 个位置

\[cnt_3\times 3-cnt_1=c_i
\]

然后我们就可以求出经过所有 \(b\) 变换的答案数组了,把它 fwt 回去即可


Code:

#include <cstdio>
#include <cctype>
const int SIZE=1<<21;
char ibuf[SIZE],*iS,*iT;
//#define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SIZE,stdin),iS==iT?EOF:*iS++):*iS++)
#define gc() getchar()
template <class T>
void read(T &x)
{
x=0;char c=gc();
while(!isdigit(c)) c=gc();
while(isdigit(c)) x=x*10+c-'0',c=gc();
}
const int mod=998244353;
const int inv2=499122177;
#define mul(x,y) (1ll*(x)*(y)%mod)
int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
int qp(int d,int k)
{
int f=1;
while(k)
{
if(k&1) f=mul(f,d);
d=mul(d,d);
k>>=1;
}
return f;
}
const int N=1<<20;
int n,lim=1,a[N];
void FWT(int *a,int lim,int typ)
{
for(int le=1;le<lim;le<<=1)
for(int i=0;i<lim;i+=le<<1)
for(int j=i;j<i+le;j++)
{
int x=a[j],y=a[j+le];
if(typ)
{
a[j]=add(x,y);
a[j+le]=add(x,mod-y);
}
else
{
a[j]=mul(add(x,y),inv2);
a[j+le]=mul(add(x,mod-y),inv2);
}
}
}
int main()
{
read(n);
for(int x,i=1;i<=n;i++)
{
read(x);
++a[0],a[x]+=2;
while(lim<=x) lim<<=1;
}
FWT(a,lim,1);
for(int i=0;i<lim;i++)
{
int cnt3=mul(a[i]+n,748683265);
//printf("%d %d\n",a[i]+n,cnt3);
int cnt1=add(n,mod-cnt3);
a[i]=qp(3,cnt3);
if(cnt1&1) a[i]=mod-a[i];
}
//for(int i=0;i<lim;i++) printf("%d ",a[i]);puts("");
FWT(a,lim,0);
printf("%d\n",add(a[0],mod-1));
return 0;
}

2019.7.8

【UNR #2】黎明前的巧克力 解题报告的更多相关文章

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

    题目描述 给出 $n$ 个数,从中选出两个互不相交的集合,使得第一个集合与第二个集合内的数的异或和相等.求总方案数. 输入 第一行一个正整数 $n$ ,表示巧克力的个数.第二行 $n$ 个整数 $a_ ...

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

    来自FallDream的博客,未经允许,请勿转载,谢谢. 传送门 很奇妙的一道题 首先不难发现一个暴力做法,就是f[i]表示异或和为i的答案数,每次FWT上一个F数组,其中F[0]=1,F[ai]=2 ...

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

    uoj description 给你\(n\)个数,求从中选出两个交集为空的非空集合异或和相等的方案数模\(998244353\). sol 其实也就是选出一个集合满足异或和为\(0\),然后把它分成 ...

  4. 「UNR#2」黎明前的巧克力

    「UNR#2」黎明前的巧克力 解题思路 考虑一个子集 \(S\) 的异或和如果为 \(0\) 那么贡献为 \(2^{|S|}\) ,不难列出生产函数的式子,这里的卷积是异或卷积. \[ [x^0]\p ...

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

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

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

    [UOJ#310][UNR#2]黎明前的巧克力(FWT) 题面 UOJ 题解 把问题转化一下,变成有多少个异或和为\(0\)的集合,然后这个集合任意拆分就是答案,所以对于一个大小为\(s\)的集合,其 ...

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

    uoj310[UNR #2]黎明前的巧克力(FWT) uoj 题解时间 对非零项极少的FWT的优化. 首先有个十分好想的DP: $ f[i][j] $ 表示考虑了前 $ i $ 个且异或和为 $ j ...

  8. UOJ #310 黎明前的巧克力 FWT dp

    LINK:黎明前的巧克力 我发现 很多难的FWT的题 都和方程有关. 上次那个西行寺无余涅槃 也是各种解方程...(不过这个题至今还未理解. 考虑dp 容易想到f[i][j][k]表示 第一个人得到巧 ...

  9. @uoj - 310@ 【UNR #2】黎明前的巧克力

    目录 @description@ @solution@ @accepted code@ @details@ @description@ Evan 和 Lyra 都是聪明可爱的孩子,两年前,Evan 开 ...

随机推荐

  1. IntelliJ IDEA中创建xml文件

      1.file—setting,左上角输入template, 2.在左侧栏找到File And Code Templates 3.中间选中Files 4.点击+号,添加模板 5.输入模板名字:Nam ...

  2. php中的构造函数与析构函数

    PHP面向对象——构造函数.析构函数 __construct.__destruct__construct 构造方法,当一个对象创建时调用此方法,使用此方法的好处是:可以使构造方法有一个独一无二的名称, ...

  3. zookeeper分布式锁用法

    package com.example.demo3.zk; import lombok.extern.slf4j.Slf4j; import org.apache.storm.shade.org.ap ...

  4. 彻底理解 Linux 的搜索工具: grep 和 awk

    grep 官方手册 awk 官方手册, awk 学习资料 1. grep grep 用于打印匹配指定模式的行. 1.1 介绍 grep 命令从输入文件中查找匹配到给定模式列表的行.发现匹配到的行后,默 ...

  5. CSS学习笔记2:选择器

    标签选择器 1.选择要给样式的目标标签,所以叫做标签选择器,也叫元素选择器. 2.给所有相同标签,给相同样式. <!DOCTYPE html> <html lang="en ...

  6. 排序,其他的运用 os fork

    while True: str_num = input("Enter number:") flag = True dotCount = 0 if str_num[0] == '-' ...

  7. jar包/class文件如何快速反编译成java文件

    有时编写的java代码打包为可执行jar包后需要查看工程结构是否是且只有我们需要的包,故需要查看jar包层级. 1.windows系统可以直接在网上下载jd-gui.exe包,然后傻瓜安装: 2.Ma ...

  8. Quartz的简单使用

    一.Quartz 介绍 Quartz是Java领域最著名的.功能丰富的.开放源码的作业调度工具,几乎可以在所有的Java应用程序中集成--从小的单机应用到大的电子商务系统. Quartz可以用来执行成 ...

  9. 【学习总结】gcc和gdb

    目录 <> vim.gcc.gdb: gcc: gcc和g++是c/c++的linux系统集成的编译器,源文件的后缀应为 .C/.cpp/.c++/.cc等 编译器可以将C.C++等语言源 ...

  10. 【JAVA】 04-Java中的多线程

    链接: 笔记目录:毕向东Java基础视频教程-笔记 GitHub库:JavaBXD33 目录: <> <> 内容待整理: 多线程引入 概述 多线程: 进程:正在执行中的程序,其 ...