• 【UNR #2】黎明前的巧克力 解题报告


    【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 imes 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
    ",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
    ",add(a[0],mod-1));
    	return 0;
    }
    

    2019.7.8

  • 相关阅读:
    计算机基础 python入门
    typora使用说明
    bay——RAC 关闭和启动顺序,状态查看.txt
    bay——巡检RAC命令_版本.txt
    bay——巡检RAC操作.txt
    bay——巡检RAC日志.txt
    bay——安装_Oracle 12C-单实例-Centos7 -DG.txt
    bay——安装_Oracle 12C-单实例-Centos7.txt
    bay——安装_RAC11g_LC_ASM方式_测试环境.txt
    bay——安装_RAC11g_LC_测试环境-rehat6+udev.txt
  • 原文地址:https://www.cnblogs.com/butterflydew/p/11149824.html
Copyright © 2020-2023  润新知