• UOJ#310 【UNR #2】黎明前的巧克力 FWT 多项式


    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ310.html

    题目传送门 - UOJ#310

    题意

      给定 $n$ 个数 ,请你选出两个不相交的集合(两个集合交换一下也算一种),问有多少种选择方案使得两个集合各自包含的数的异或值 相等。

      不能两个都不选。

      $n,a_ileq 10^6$

    题解

      首先,问题可以转化成:选择两个集合,他们的异或值为 $0$ 。

      我们可以构造幂级数。

      对于 $a_i$ 我们构造: $h_i(x)=x^0+2x^{a_i}$ 。

      表示的意义是不选 $a_i$ 有一种方案,选择 $a_i$ 可以把它随便扔给两个集合,有两种方案。

      于是我们只需要把所有的这些幂级数做一个异或卷积就可以了。这里注意一下我们可以通过把每一个多项式的 FWT 乘起来得到最终式子的 FWT 。

      但是直接 FWT 显然要 TLE 。

      我们考虑观察一下这个东西的特殊性质。

      对于同一个多项式 $f$ ,我们观察到 $f_i$ 只有两个系数不为 $0$ 的:$f_0=1,f_{a_i}=2$

      考虑 FWT 的变换式(注意一下这里的 $f_0$ 和 $f_1$ 的意义略有不同,这里是分别指 $f$ 的左边一半和右边一半):

    $$FWT(f)=(FWT(f_0+f_1),FWT(f_0-f_1))$$

      仔细分析可以发现:$f_0$ 对于任意 $FWT(f)_i$ 的贡献都为 $1$ 。而 $f_{a_i}$ 对任意 $FWT(f)_i$ 的贡献只有 $pm 2$ 两种。

      于是 $FWT(f)_i=-1$ 或 $FWT(f)_i=3$ 。

      得到这个结论可以干什么?我们仍然不能把它暴力乘起来。

      但是我们如果得到了所有式子的 FWT 之和,是不是就可以得到 $-1$ 和 $3$ 的个数了?

      对于 FWT ,我们有 $FWT(f+g)=FWT(f)+FWT(g)$ ,即所有多项式的和的 FWT 等于 所有的多项式的 FWT 之和。

      于是我们可以一次 FWT 得到 对于每一个下标的 ,所有多项式的 FWT 的该下标的值的和。

      于是我们可以对于每一个下标,解出这个下标的 $-1$ 的个数,设为 $x$ ,那么,我们就可以得到我们一开始需要的:乘积 $=(-1)^x3^{n-x}$ 。

      然后再 IFWT 回来。

      由于要除掉都不选的情况,$f_0-1$ 就是答案。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1<<20,mod=998244353;
    const int inv2=499122177,inv4=748683265;
    int n,m=1<<20,a[N],Pow3[N];
    void FWT(int a[],int n,int flag){
    	for (int d=1;d<n;d<<=1)
    		for (int i=0;i<n;i+=(d<<1))
    			for (int j=0;j<d;j++){
    				int x=a[i+j],y=a[i+j+d];
    				a[i+j]=(x+y)%mod;
    				a[i+j+d]=(x-y+mod)%mod;
    				if (flag==-1){
    					a[i+j]=1LL*a[i+j]*inv2%mod;
    					a[i+j+d]=1LL*a[i+j+d]*inv2%mod;
    				}
    			}
    }
    int main(){
    	scanf("%d",&n);
    	memset(a,0,sizeof a);
    	for (int i=1,x;i<=n;i++){
    		scanf("%d",&x);
    		a[x]+=2,a[0]++;
    	}
    	FWT(a,m,1);
    	Pow3[0]=1;
    	for (int i=1;i<m;i++)
    		Pow3[i]=1LL*Pow3[i-1]*3%mod;
    	for (int i=0;i<m;i++){
    		int x=(1LL*(3*n-a[i])*inv4%mod+mod)%mod;
    		if (x&1)
    			a[i]=(-Pow3[n-x]+mod)%mod;
    		else
    			a[i]=Pow3[n-x];
    	}
    	FWT(a,m,-1);
    	printf("%d",(a[0]+mod-1)%mod);
    	return 0;
    }
    

      

  • 相关阅读:
    matlab 动态绘图保持figure不变
    ucos-ii在ti dsp 28377芯片上的运行过程和移植过程
    关于ucos_ii 就绪表的理解
    dsp 28377在线升级 实例总结
    关于DSP的boot mode / boot loader /上电顺序 /在线升级等问题的总结
    开源看板wekan docker 源码构建
    开源看板 wekan windows 环境下 离线部署
    公司内网两台电脑无法ping通的问题
    excle 根据单位、岗位、成绩 等排名
    python爬虫学习:从数据库读取目标爬虫站点及爬虫规则,批量爬取目标站点指定数据(scrapy框架)
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/UOJ310.html
Copyright © 2020-2023  润新知