zoukankan      html  css  js  c++  java
  • Codeforces 662 C. Binary Table

    http://codeforces.com/contest/662/problem/C

    题意:
    n行m列01矩阵,每次可以反转一行或一列,问最后最少可以剩下多少个1

    n只有20,把行状态压缩

    操作奇数次相当于1次,操作偶数次相当于不操作

    所以可以枚举对行的操作,将操作也状态压缩

    A[i] 表示有多少列的状态为i

    B[i] 表示 状态为i时的最优解,即fanzh

    C[i] 表示 操作i的最优解

    执行一次行操作相当于给某一列的状态异或上操作的状态

    C[opt] = Σ A[state]*B[opt xor state]

    (先执行这种行操作,如果某一列发现再执行一次列操作更优,那这一列再执行列操作,这通通包含在B数组里)

    目前求C的复杂度为 2^2n

    令 res = opt xor state

    C[opt] = Σ(state) Σ(res)   [state xor res == opt] A[state]*B[res]

    C[opt] = Σ(state) Σ(res)   [state xor opt == res] A[state]*B[res]

    然后就可以用FWT 优化 成2^n * n

    这还有个用子集反演的,是什么啊??

    http://blog.csdn.net/QWsin/article/details/55054071

    #include<cstdio>
    #include<algorithm>
    
    using namespace std;
    
    typedef long long LL;
    
    char s[21][100002];
    
    LL a[1048578],b[1048578],c[1048576];
    
    int count(int i)
    {
        int sum=0;
        while(i) sum+=i&1,i>>=1;
        return sum;
    }
    
    void FWT_xor(LL *a,int n)
    {
        LL x,y;
        for(int d=1;d<n;d<<=1)
            for(int m=d<<1,i=0;i<n;i+=m)
                for(int j=0;j<d;++j)
                {
                    x=a[i+j]; y=a[i+j+d];
                    a[i+j]=x+y; a[i+j+d]=x-y;
                }
    }
    
    void IFWT_xor(LL *a,int n)
    {
        LL x,y;
        for(int d=1;d<n;d<<=1)
            for(int m=d<<1,i=0;i<n;i+=m)
                for(int j=0;j<d;++j)
                {
                    x=a[i+j]; y=a[i+j+d];
                    a[i+j]=x+y>>1; a[i+j+d]=x-y>>1;
                }
    }
    
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) scanf("%s",s[i]+1);
        int state;
        for(int i=1;i<=m;++i)
        {
            state=0;
            for(int j=1;j<=n;++j)
                if(s[j][i]=='1') state|=1<<j-1;
            ++a[state];
        }
        int S=1<<n,sum;
        for(int i=0;i<S;++i) 
        {
            sum=count(i);
            b[i]=min(sum,n-sum);
        }
        FWT_xor(a,S);
        FWT_xor(b,S);
        for(int i=0;i<S;++i) c[i]=a[i]*b[i];
        IFWT_xor(c,S);
        LL ans=n*m;
        for(int i=0;i<S;++i) ans=min(ans,c[i]);
        printf("%I64d",ans);
    }
  • 相关阅读:
    Jxl 简单运用 Excel创建,插入数据,图片,更新数据,
    tomcat端口号被占用
    QQ、MSN、淘包旺旺、Skype临时对话的html链接代码
    验证信息
    wpf学习笔记数据绑定功能总结
    wpfStyle注意点
    wpf轻量绘图DrawingVisual
    wpfDrawingBrush注意点
    wpf容易误解的Image
    wpf装饰器
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8595976.html
Copyright © 2011-2022 走看看