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;
    }
  • 相关阅读:
    教你作一份高水准的简历
    python并发
    阻塞,非阻塞,同步,异步
    python三层架构
    paramiko与ssh
    python-进程
    生产者消费者模型
    python-线程
    python-socket
    python-mysql
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/15519174.html
Copyright © 2011-2022 走看看