码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2020-02-05 21:50:31      阅读:75      评论:0      收藏:0      [点我收藏+]

标签:数值   ons   解方程   amp   return   这一   题解   include   pop   

题目描述

题解

考虑到选出的两个集合的异或值为 $0$ ,所以我们可以看做找出集合,其异或值为 $0$ ,然后如果这个集合大小是 $x$ ,对答案的贡献就是 $2^x$

所以我们考虑每个 $i$ 对应一个多项式 $(1+2x^{a_i})$ ,只要我们把多项式乘起来即可

我们考虑 $fwt$ 过程中 $i$ 位置上的数对 $j$ 位置的贡献是数值乘上 $(-1)^{popcount(i\And j)}$ ,不难发现每个多项式 $fwt$ 后数值要么是 $-1$ ,要么是 $3$

所以我们可以把这些多项式相加后做 $fwt$ ,然后设这个位置有 $x$ 个 $-1$,那就有 $n-x$ 个 $3$ ,解方程即可,然后这一位将变成 $(-1)^x3^{n-x}$,之后再做 $ifwt$ 即可

最后答案因为不能选出空集所以要减一

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1<<20,P=998244353;
const int U=(P+1)>>1,V=748683265;
int n,a[N],w[N];
void fwt(int *a,int o){
    for (int i=1;i<N;i<<=1)
        for (int j=0;j<N;j+=(i<<1))
            for (int x,y,k=0;k<i;k++){
                x=a[j+k];y=a[i+j+k];
                a[j+k]=(x+y)%P;a[i+j+k]=(x-y+P)%P;
                if (o) a[j+k]=1ll*a[j+k]*U%P,
                    a[i+j+k]=1ll*a[i+j+k]*U%P;
            }
}
int main(){
    scanf("%d",&n);w[0]=1;
    for (int i=1;i<N;i++) w[i]=3ll*w[i-1]%P;
    for (int x,i=1;i<=n;i++)
        scanf("%d",&x),a[0]++,a[x]+=2;
    fwt(a,0);for (int x,i=0;i<N;i++)
        x=1ll*(3*n-a[i]+P)*V%P,
        a[i]=1ll*((x&1)?P-1:1)*w[n-x]%P;
    fwt(a,1);cout<<(a[0]+P-1)%P<<endl;return 0;
}

 

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

标签:数值   ons   解方程   amp   return   这一   题解   include   pop   

原文地址:https://www.cnblogs.com/xjqxjq/p/12266789.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!