zoukankan      html  css  js  c++  java
  • cf103202M. United in Stormwind

    题目描述

    题解

    假设选出题目的集合为 $S$ ,考虑求出它的数对数。

    $(i,j)$ 如果不相同,则 $a_i ext{xor} a_j & S=0$ 。

    因此我们先用 $ ext{fwt}$ 求出异或值为 $T$ 的数对数,然后对于 $S$ 来说,如果 $T$ 上的值能贡献答案,说明 $S &T>0$ 。

    考虑容斥,减去 $S&T=0$ 的数对数即可。

    也就是说, $T$ 的补集包含了 $S$ 。

    因此考虑 $ ext{sosdp}$ , $f_{i,j}$ 表示 $x&i=x$ 并且 $x ext{xor} i<2^j$的 $x$ 的答案的和。

    考虑转移,如果 $i$ 的第 $j$ 位为 $0$ ,那么 $f_{i,j}=f_{i,j-1}$ ,否则 $f_{i,j}=f_{i,j-1}+f_{i ext{xor} 2^j,j-1}$ 。

    效率: $O(m2^m)$ 。

    代码

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int N=1<<20;
    int n,m,a[N],t,ans;
    LL Z,A[N<<1],B[N<<1],f[N];
    char ch[25];
    void Fwt(LL *g,int o){
        for (int i=1;i<t;i<<=1)
            for (int j=0;j<t;j+=(i<<1))
                for (int k=0;k<i;k++){
                    LL x=g[j+k],y=g[i+j+k];
                    g[j+k]=x+y;g[i+j+k]=x-y;
                    if (!o) g[j+k]/=2,g[i+j+k]/=2;
                }
    }
    int main(){
        cin>>n>>m>>Z;
        for (int i=1;i<=n;i++){
            scanf("%s",ch);
            for (int j=0;j<m;j++)
                a[i]=(a[i]<<1)|(ch[j]=='A');
            A[a[i]]++;B[a[i]]++;
        }
        t=1<<m+1;Fwt(A,1);Fwt(B,1);
        for (int i=0;i<t;i++) A[i]*=B[i];
        Fwt(A,0);t>>=1;
        for (int i=0;i<t;i++) f[i]=A[i];
        for (int i=0;i<m;i++)
            for (int j=0;j<t;j++)
                if (j&(1<<i)) f[j]+=f[j^(1<<i)];
        for (int i=0;i<t;i++){
            LL v=1ll*n*n-f[(t-1)^i];
            if (v>=Z+Z) ans++;
        }
        cout<<ans<<endl;return 0;
    }
  • 相关阅读:
    子页面向父页面传值
    UEditor的使用方法
    MVC 生成PDf表格并插入图片
    简单行列转换记录
    此数据库没有有效所有者“的解决,我很受用
    ASP.NET MVC3 使用kindeditor编辑器获取不到值
    c#读写文件
    VB 中Sub和Function的区别
    问题集
    hadoop2.7.2运行例子时报错
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/15519174.html
Copyright © 2011-2022 走看看