• CF704C Black Widow


    因为一个 (x_i) 不会出现超过两次,因此将有相同 (x_i) 的表达式之间连边,得到的图为若干链和环。

    (f_{i,0/1,0/1,0/1}) 为考虑了链或环的前 (i) 个点,第一个点的状态,上一个变量的状态,现在的异或和状态的方案数,分类讨论来转移,最后将所有连通块的信息合并。

    要注意处理自环和孤立点的情况。

    #include<bits/stdc++.h>
    #define maxn 200010
    #define p 1000000007
    using namespace std;
    typedef long long ll;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    int n,m,tot;
    int bel[maxn],deg[maxn];
    ll f[maxn][2][2][2],g[maxn][2],h[maxn][2];
    bool vis[maxn];
    struct node
    {
        int k;
        int v[2];
    }a[maxn];
    struct edge
    {
        int to,nxt,v;
    }e[maxn];
    int head[maxn],edge_cnt=1;
    void add(int from,int to,int val)
    {
        e[++edge_cnt]={to,head[from],val},head[from]=edge_cnt;
        e[++edge_cnt]={from,head[to],val},head[to]=edge_cnt;
        deg[from]++,deg[to]++;
    }
    void dfs(int x,int link)
    {
        if(!link)
        {
            f[x][0][0][0]=1;
            f[x][1][1][0]=a[x].k==2;
        }
        vis[x]=true;
        int cnt=0;
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(cnt==1) break;
            if(i==link||(i^1)==link) continue;
            cnt++;
            bool flag;
            for(int j=0;j<a[x].k;++j)
                for(int k=0;k<a[y].k;++k)
                    if(abs(a[x].v[j])==abs(a[y].v[k])&&abs(a[x].v[j])==e[i].v)
                        flag=(a[x].v[j]==-a[y].v[k]);
            if(vis[y])
            {
                if(!flag)
                {
                    g[tot][0]=(f[x][0][0][0]+f[x][0][1][1]+f[x][1][0][1]+f[x][1][1][1])%p;
                    g[tot][1]=(f[x][0][1][0]+f[x][0][0][1]+f[x][1][0][0]+f[x][1][1][0])%p;
                }
                else
                {
                    g[tot][0]=(f[x][0][1][1]+f[x][1][0][0]+f[x][0][0][1]+f[x][1][1][1])%p;
                    g[tot][1]=(f[x][0][0][0]+f[x][0][1][0]+f[x][1][1][0]+f[x][1][0][1])%p;
                }
            }
            else
            {
                if(!flag)
                {
                    for(int j=0;j<=1;++j)
                    {
                        f[y][j][1][1]=(f[y][j][1][1]+f[x][j][0][0])%p;
                        f[y][j][0][0]=(f[y][j][0][0]+f[x][j][0][0])%p;
                        f[y][j][1][1]=(f[y][j][1][1]+f[x][j][1][0])%p;
                        f[y][j][0][1]=(f[y][j][0][1]+f[x][j][1][0])%p;
                        f[y][j][1][0]=(f[y][j][1][0]+f[x][j][0][1])%p;
                        f[y][j][0][1]=(f[y][j][0][1]+f[x][j][0][1])%p;
                        f[y][j][1][0]=(f[y][j][1][0]+f[x][j][1][1])%p;
                        f[y][j][0][0]=(f[y][j][0][0]+f[x][j][1][1])%p;
                    }
                }
                else
                {
                    for(int j=0;j<=1;++j)
                    {
                        f[y][j][0][1]=(f[y][j][0][1]+f[x][j][0][0])%p;
                        f[y][j][1][0]=(f[y][j][1][0]+f[x][j][0][0])%p;
                        f[y][j][1][1]=(f[y][j][1][1]+f[x][j][1][0])%p;
                        f[y][j][0][1]=(f[y][j][0][1]+f[x][j][1][0])%p;
                        f[y][j][1][1]=(f[y][j][1][1]+f[x][j][0][1])%p;
                        f[y][j][0][0]=(f[y][j][0][0]+f[x][j][0][1])%p;
                        f[y][j][1][0]=(f[y][j][1][0]+f[x][j][1][1])%p;
                        f[y][j][0][0]=(f[y][j][0][0]+f[x][j][1][1])%p;
                    }
                }
                dfs(y,i);
            }
        }
        if(!cnt)
        {
            if(a[x].k==1)
            {
                g[tot][0]=(f[x][0][1][1]+f[x][0][0][0]+f[x][1][0][0]+f[x][1][1][1])%p;
                g[tot][1]=(f[x][0][0][1]+f[x][0][1][0]+f[x][1][0][1]+f[x][1][1][0])%p;
            }
            else
            {
                g[tot][0]=(f[x][0][0][1]+f[x][0][1][1]+f[x][1][0][1]+f[x][1][1][1]+f[x][0][0][0]+f[x][0][1][1]+f[x][1][0][0]+f[x][1][1][1])%p;
                g[tot][1]=(f[x][0][0][0]+f[x][0][1][0]+f[x][1][0][0]+f[x][1][1][0]+f[x][0][0][1]+f[x][0][1][0]+f[x][1][0][1]+f[x][1][1][0])%p;
            }
        }
    }
    int main()
    {
        read(n),read(m);
        for(int i=1;i<=n;++i)
        {
            read(a[i].k);
            for(int j=0;j<a[i].k;++j)
            {
                read(a[i].v[j]);
                int id=abs(a[i].v[j]);
                if(!bel[id]) bel[id]=i;
                else
                {
                    if(i!=bel[id]) add(i,bel[id],id);
                    else
                    {
                        vis[i]=true,tot++;
                        if(a[i].v[0]==a[i].v[1]) g[tot][0]=g[tot][1]=1;
                        else g[tot][1]=2;
                    }
                    bel[id]=-1;
                }
            }
        }
        for(int i=1;i<=m;++i)
        {
            if(a[bel[i]].k!=1) continue;
            vis[bel[i]]=true,tot++,g[tot][0]=g[tot][1]=1;
        }
        for(int i=1;i<=n;++i)
            if(!vis[i]&&deg[i]==1)
                tot++,dfs(i,0);
        for(int i=1;i<=n;++i)
            if(!vis[i])
                tot++,dfs(i,0);
        h[0][0]=1;
        for(int i=1;i<=tot;++i)
        {
            h[i][0]=(h[i-1][0]*g[i][0]%p+h[i-1][1]*g[i][1]%p)%p;
            h[i][1]=(h[i-1][0]*g[i][1]%p+h[i-1][1]*g[i][0]%p)%p;
        }
        for(int i=1;i<=m;++i)
        	if(!bel[i])
        		h[tot][1]=h[tot][1]*2%p;
        printf("%lld",h[tot][1]);
        return 0;
    }
    
  • 相关阅读:
    每天一个linux命令(25):linux文件属性详解
    每天一个linux命令(24):Linux文件类型与扩展名
    每天一个linux命令(23):Linux 目录结构
    每天一个linux命令(22):find 命令的参数详解
    每天一个linux命令(21):find命令之xargs
    每天一个linux命令(20):find命令之exec
    每天一个linux命令(19):find 命令概览
    Unity3D自己常用代码
    Unity导入FBX自动进行动画切分
    Unity和虚幻的比较
  • 原文地址:https://www.cnblogs.com/lhm-/p/13871117.html
Copyright © 2020-2023  润新知