zoukankan      html  css  js  c++  java
  • bzoj4671: 异或图

    感觉跟这题很像bzoj2839: 集合计数

    首先这个和子集没有关系,但和点的划分有关

    考虑枚举点的划分,设gi表示把点分成至少分成i个块的方案数,fi去掉至少

    和那题类似的想法,对于大小为x的划分,它对gi的贡献为S2(i,x)

    所以有gi=sigema(1~i)x S2(i,x)*fi

    上斯特林反演

    fi=sigema(1~i)x (-1)^(i-x) * S1(i,x) * gi

    只需要算f1,即算 sigema(1~i)x (-1)^(i-1) * S1(i,1) * gi = sigema(1~i)x (-1)^(i-1) * (i-1)! * gi

    所以就是算gi就可以了,爆搜划分,把必须要不联通的搞出来,对于每个图是一个异或方程,解异或方程组,计算解的方案数即自由元个数,这里没必要高斯消元,用线性基判断就可以了

    注意假如是nm^2枚举边和点check会T,要加上时间戳,一个是在线性基里这个基是否存在,一个是当前这条边是否必须要不联通,这样下来复杂度就被卡到m^2+n*m,勉强过了,bzoj中游水准

    注意斯特林反演x的下标从0从1开始都没有区别,因为斯特林数除了0,0是1其他i,0都是0   ORZ%%%%zory神犇

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<bitset>
    using namespace std;
    typedef long long LL;
    const int maxn=110;
    const int maxm=20;
    LL fac[maxm];
    void pre(){fac[0]=1;for(int i=1;i<=maxm;i++)fac[i]=fac[i-1]*i;}
    
    //-------------------------------------------def----------------------------------------------------------
    
    int n,m,len;bitset<maxm*maxm>mp[maxn],lt[maxm*maxm],p;
    int tim,v[maxm*maxm],ti[maxm*maxm];
    bool insert(int t)
    {
        p=mp[t];
        for(int i=len;i>=1;i--)
            if(p[i]==1&&v[i]==tim)
            {
                if(ti[i]!=tim)
                {
                    ti[i]=tim;
                    lt[i]=p;
                    return true;
                }
                else p^=lt[i];
            }
        return false;
    }
    
    //------------------------------------------线性基--------------------------------------------------------
    
    int num,b[maxm];LL ans;
    void dfs(int k)
    {
        if(k==m+1)
        {
            len=0; tim++;
            for(int i=1;i<=m;i++)
                for(int j=i+1;j<=m;j++)
                {
                    len++; 
                    if(b[i]!=b[j])v[len]=tim;
                }
            int sum=0;
            for(int t=1;t<=n;t++)
                sum+=(insert(t)==false);
            
            ans+=(num%2==0?-1:1)*fac[num-1]*(1LL<<sum);
            return ;
        }
        
        for(int i=1;i<=num;i++)
        {
            b[k]=i;
            dfs(k+1);
        }
        b[k]=++num;
        dfs(k+1);
        num--;
    }
    
    char ss[maxm];
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        pre();
        scanf("%d",&n);
        for(int t=1;t<=n;t++)
        {
            scanf("%s",ss+1),m=strlen(ss+1);
            for(int i=1;i<=m;i++)mp[t][i]=(ss[i]=='1');
        }
        for(int i=2;i<=10;i++)if(m==i*(i-1)/2){m=i;break;}
        dfs(1);
        printf("%lld
    ",ans);
        
        return 0;
    }
  • 相关阅读:
    RxJava+okhttp3
    RetrofitOkHttp网络请求
    布局111
    网络请求展示数据
    一级列表展示购物车
    终极MVP二级购物车
    将博客搬至CSDN
    nyoj-开灯问题
    nyoj-数乌龟
    nyoj 正三角形的外接圆面积
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10329460.html
Copyright © 2011-2022 走看看