zoukankan      html  css  js  c++  java
  • uoj310. 【UNR #2】黎明前的巧克力

    题目描述:

    uoj

    题解:

    WTF。

    看题解看了一个小时才看明白。

    首先有状态$f[i][j]$表示前$i$个东西两人取,最后两人异或和为$j$的有多少方案。

    转移为$f[i][j]=f[i-1][j]+2*f[i-1][j oplus a[i]]$。

    显然跑FWT做异或卷积(显然会T)。

    发现卷积中每次卷的是{1,0,0,……,0,2,0……}这样一个东西。

    打表发现FWT后每一项是-1或3。

    其实很好解释,从贡献的角度讲,0位的贡献都是1,而$a[i]$位的贡献是2或-2,所以是3或-1。

    考虑将所有的$a[i]$放在一起做FWT。

    这样的话每组对每一位上的贡献是-1或3,共有$n$组,贡献和为$s$。

    设贡献为$3$的有$x$组,那么$3x-(n-x)=s$,有$x=frac{n+s}{4}$。

    然后快速幂再卷回去就好了。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 2000050;
    const int MOD = 998244353;
    const int inv_2 = (MOD+1)/2;
    const int inv_4 = 1ll*inv_2*inv_2%MOD;
    template<typename T>
    inline void read(T&x)
    {
        T f = 1,c = 0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x = f*c;
    }
    template<typename T>inline void Mod(T&x){if(x>=MOD)x-=MOD;}
    ll fastpow(ll x,int y)
    {
        ll ret = 1;
        while(y)
        {
            if(y&1)ret=ret*x%MOD;
            x=x*x%MOD;y>>=1;
        }
        return ret;
    }
    int n,a[N],lim;
    void fwt(int*a,int len,int k)
    {
        for(int i=1;i<len;i<<=1)
            for(int j=0;j<len;j+=(i<<1))
                for(int o=0;o<i;o++)
                {
                    int w1 = a[j+o],w2 = a[j+o+i];
                    Mod(a[j+o] = w1+w2),Mod(a[j+o+i]=w1+MOD-w2);
                    if(k==-1)a[j+o]=1ll*a[j+o]*inv_2%MOD,a[j+o+i]=1ll*a[j+o+i]*inv_2%MOD;
                }
    }
    int main()
    {
        read(n);int mx=0;
        for(int i=1,x;i<=n;i++)
        {
            read(x);
            if(x>mx)mx=x;
            a[0]++,a[x]+=2;
        }
        lim = 1;
        while(lim<=mx)lim<<=1;
        fwt(a,lim,1);
        for(int i=0;i<lim;i++)
        {
            int now = 1ll*(n+a[i])*inv_4%MOD;
            a[i] = fastpow(3,now);
            if((n-now)&1)a[i]=MOD-a[i];
        }
        fwt(a,lim,-1);
        printf("%d
    ",(a[0]+MOD-1)%MOD);
        return 0;
    }
    View Code
  • 相关阅读:
    Mermaid | 强大的画图渲染脚本
    Tools | windows剪切板增强版
    Eclipse | eclipse食用教程
    WebSites | 常用工具网站
    Extensions | Extension && Plugins
    Java | IDE-Eclipse下载安装
    敲个采药玩玩
    今日sb题之 sdnuoj 1064
    stl概述
    给定 n 个字符串,求有多少字符串是其他字符串的前缀。
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/11154733.html
Copyright © 2011-2022 走看看