zoukankan      html  css  js  c++  java
  • UOJ 310 黎明前的巧克力(FWT)

    【题目链接】 http://uoj.ac/problem/310

    【题目大意】

      给出一个数集,A从中选择一些数,B从中选择一些数,不能同时不选
      要求两者选择的数异或和为0,问方案数

    【题解】

      题目等价于选取一个非空且xor为0的集合并将其拆分为两个子集的方案数
      用dp表示xor为j的方案数,易得dp方程dp[i][j]=dp[i-1][j]+2*dp[i-1][j^a[i]]
      该式等价于dp数组与只有两个元素有值的g[0]=1,g[a[i]]=2的数组做卷积运算
      对g数组进行反演可以发现每次卷积的数组只包含3和-1,
      那么我们只要知道对一个下标来说,做的n次卷积中有几个3和-1,
      就能够直接乘算出答案,根据FWT的和等于和的FWT,我们将多次需要做卷积的数组相加,
      一并做FWT,得到他们和的反演值,在每个位置解关于3和-1的二元一次方程组,
      再将其替换为正确值,最后FWT求逆之后下标为0的答案减去1就是答案,
      减一是因为两个人取数不能同时为空。

    【代码】

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int P=998244353;
    const int inv2=(P+1)>>1;
    const int N=2000000;
    void FWT(int*a,int n){
        for(int d=1;d<n;d<<=1)for(int m=d<<1,i=0;i<n;i+=m)for(int j=0;j<d;j++){
            int x=a[i+j],y=a[i+j+d];
            a[i+j]=(x+y)%P,a[i+j+d]=(x-y+P)%P;
        }
    }
    void UFWT(int*a,int n){
        for(int d=1;d<n;d<<=1)for(int m=d<<1,i=0;i<n;i+=m)for(int j=0;j<d;j++){
            int x=a[i+j],y=a[i+j+d];
            a[i+j]=1LL*(x+y)*inv2%P,a[i+j+d]=1LL*(x-y)*inv2%P;
        }
    }
    int n,x,mx,pw[N],a[N];
    int main(){
        pw[0]=1;
        for(int i=1;i<N;i++)pw[i]=3LL*pw[i-1]%P;
        while(~scanf("%d",&n)){
        	memset(a,0,sizeof(a));
            for(int i=mx=1;i<=n;i++){
                scanf("%d",&x);
                a[0]++; a[x]+=2;
                mx=max(mx,x);
            }
            int m=1;
            while(m<=mx)m<<=1;
            FWT(a,m);
            for(int i=0;i<m;i++){
                x=(3ll*n+P-a[i])*inv2%P*inv2%P;
                a[i]=(x&1)?(P-pw[n-x])%P:pw[n-x];
            }
            UFWT(a,m);
            printf("%d
    ",(a[0]+P-1)%P);
        }
        return 0;
    }
  • 相关阅读:
    AngularJs+bootstrap搭载前台框架——准备工作
    AngularJs+bootstrap搭载前台框架——基础页面
    AngularJs调用Restful实现CRUD
    用AngularJs制作单页面应用
    Unity3D中使用Projector生成阴影
    Linux OpenGL 实践篇-16 文本绘制
    leetcode 233. 数字1的个数
    leetcode 189. 轮转数组
    leetcode 127 单词接龙
    leetcode 4.两个排序数组的中位数
  • 原文地址:https://www.cnblogs.com/forever97/p/uoj310.html
Copyright © 2011-2022 走看看