zoukankan      html  css  js  c++  java
  • [UOJ UNR#2 黎明前的巧克力]

    来自FallDream的博客,未经允许,请勿转载,谢谢。


    传送门

    很奇妙的一道题

    首先不难发现一个暴力做法,就是f[i]表示异或和为i的答案数,每次FWT上一个F数组,其中F[0]=1,F[ai]=2,最后输出f[0]即可。

    这样我就考虑从FWT之后的数组入手。

    首先发现F[0]=1只会让最后的数组全部+1,所以只考虑F[ai]=2的影响。

    发现每个项只会是3或者-1,这取决于FWT过程中的取反次数。

    所以可以设计一个dp,f[i][x]表示分治到第i层,x是2的方案数,F[i][x]表示....,x是-2的方案数。

    这样模拟FWT进行dp即可,最后通过快速幂计算出变换后最终的数组,再逆变换回去就是答案啦。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define MN 1048576
    #define mod 998244353
    using namespace std;
    inline int read()
    {
        int x=0;char ch=getchar();
        while(ch<'0'||ch>'9') ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x;
    }
    const int Inv2=(mod+1)/2;
    int s[MN+5],S[MN+5],n,f[22][MN+5],F[22][MN+5],num[MN+5],sum;
    
    inline int pow(int x,int k)
    {
        for(sum=1;k;k>>=1,x=1LL*x*x%mod)
            if(k&1) sum=1LL*sum*x%mod;
        return sum;
    }
    
    void FWT(int l,int r)
    {
        if(l==r) return;
        int mid=l+r>>1;FWT(l,mid);FWT(mid+1,r);
        for(int i=0;i<=mid-l;++i)
        {
            int x=s[l+i],y=s[mid+1+i];
            s[l+i]=1LL*(x+y)*Inv2%mod;
            s[mid+1+i]=1LL*(x-y+mod)*Inv2%mod;
        }
    }
    
    void Solve(int l,int r,int dep)
    {
        if(l==r){f[dep][l]=num[l];return;}
        int mid=l+r>>1;Solve(l,mid,dep+1);Solve(mid+1,r,dep+1);
        for(int i=0;i<=mid-l;++i)
        {
            f[dep][l+i]=f[dep+1][l+i]+f[dep+1][mid+1+i];
            F[dep][l+i]=F[dep+1][l+i]+F[dep+1][mid+1+i];
            f[dep][mid+1+i]=f[dep+1][l+i]+F[dep+1][mid+1+i];
            F[dep][mid+1+i]=F[dep+1][l+i]+f[dep+1][mid+1+i];
        }
    }
    
    int main()
    {
        n=read();
        for(int i=1;i<=n;++i) ++num[read()];
        Solve(0,MN-1,1);
        for(int i=0;i<MN;++i)
        {
            s[i]=pow(3,f[1][i]);
            if(F[1][i]&1) s[i]=(mod-s[i])%mod;
        }
        FWT(0,MN-1);
        printf("%d
    ",(s[0]-1+mod)%mod);
        return 0;
    }
  • 相关阅读:
    【转载】三元运算符 使用小技巧一则 – javascript
    Mysql、SqlServer和Oracle 添加修改删除字段
    Jquery闪烁提示特效
    【转载】jQuery.validate 中文API
    Js取数组中最大值和最小值
    Visual Studio 2010快捷键大全
    JS 在指定数组中随机取出N个不重复的数据
    数据库 索引的优点和缺点
    OnClientClick和OnClick同时使用!
    JS 判断输入字符串的长度(中文占用两个字节,英文占用一个字节)
  • 原文地址:https://www.cnblogs.com/FallDream/p/uoj310.html
Copyright © 2011-2022 走看看