• CodeForces


    题目大意:给你一个逻辑表达式,然后让你计算表达式为真的取值情况数,表达式由一系列的 a 或者 a|b 亦或起来,每个变量最多出现两次(包括反变量)

    嘴炮开始:每个变量最多出现两次,那么跟它相关联的变量也最多是两个,转化成图的话,那么整个图就是由很多链和很多环组成,分别DP就好了;

    链DP很简单,从一段DP到另一端就可以了

    环上的DP就是先确定一个点的值然后链DP就好了,一个环DP两次

    写起来感觉还是有点麻烦。。

    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int mod=1e9+7;
    const int maxn=100100*2;
    int n,m,d[maxn];
    int fir[maxn],last[maxn<<2],nex[maxn<<2],a[maxn<<2],b[maxn<<2],tot=1;
    vector <int> e[maxn];
    bool vis[maxn];
    long long dp[maxn][2][2];
    
    int sgn(int x)
    {
        if(x>0)return 0;
        if(x<0)return 1;
    }
    
    void add(int u,int v,int aa,int bb)
    {
        ++tot;
        last[tot]=v;
        a[tot]=aa;
        b[tot]=bb;
        nex[tot]=fir[u];
        fir[u]=tot;
    }
    
    struct node{
        int a,b;
    }fa[maxn];
    bool evis[maxn<<2];
    int s[maxn],cnt;
    
    void dfs(int x)
    {
        //printf("%d
    ",x);
        vis[x]=1;
        s[++cnt]=x;
        for(int i = fir[x];i;i=nex[i])
        {
            if(!evis[i])
            {
                evis[i]=1;
                evis[i^1]=1;
                fa[x]=(node){a[i],b[i]};
                if(!vis[last[i]])dfs(last[i]);
            }
        }
    }
    
    void up(long long &a,long long b)
    {
        a+=b;
        a%=mod;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        long long ans1=0,ans0=1;
        for(int i = 1;i <= n;i++)
        {
            int k;
            scanf("%d",&k);
            if(k==1)
            {
                int x;
                scanf("%d",&x);
                e[abs(x)].push_back(sgn(x));
            }
            else
            {
                int u,v;
                scanf("%d%d",&u,&v);
                if(abs(u)==abs(v))
                {
                    if(u!=v)
                    {
                        vis[abs(u)]=1;
                        swap(ans1,ans0);
                        ans1=ans1*2%mod;
                        ans0=ans0*2%mod;
                    }
                    else
                    {
                        e[abs(u)].push_back(sgn(u));
                    }
                    continue;
                }
                add(abs(u),abs(v),sgn(u),sgn(v));
                add(abs(v),abs(u),sgn(v),sgn(u));
                d[abs(u)]++;
                d[abs(v)]++;
            }
        }
        for(int i = 1;i <= m;i++)
            if(!vis[i] && d[i]==0 && e[i].size()>0)
            {
                vis[i]=1;
                if(e[i].size()==1)
                {
                    ans1=(ans1+ans0)%mod;
                    ans0=ans1;
                }
                else
                {
                    if(e[i][0]==e[i][1])
                    {
                        ans1=ans1*2%mod;
                        ans0=ans0*2%mod;
                    }
                    else
                    {
                        swap(ans1,ans0);
                        ans1=ans1*2%mod;
                        ans0=ans0*2%mod;
                    }
                }
                //printf("%I64d %I64d
    ",ans1,ans0);
            }
        for(int i = 1;i <= m;i++)
            if(d[i]==1 && !vis[i])
            {
                cnt=0;
                dfs(i);
                dp[i][0][0]=1;
                dp[i][0][1]=0;
                dp[i][1][0]=1;
                dp[i][1][1]=0;
                if(e[i].size())
                {
                    if(e[i][0]==1)
                    {
                        swap(dp[i][0][0],dp[i][0][1]);
                    }
                    else
                    {
                        swap(dp[i][1][0],dp[i][1][1]);
                    }
                }
                for(int step = 1;step < cnt;step++)
                {
                    for(int ii = 0;ii < 2;ii++)
                        for(int jj = 0;jj < 2;jj++)
                            for(int kk = 0;kk < 2;kk++)
                            {
                                up(dp[s[step+1]][kk][((ii^fa[s[step]].a)|(kk^fa[s[step]].b))^jj],dp[s[step]][ii][jj]);
                            }
                }
                int x=s[cnt];
                if(e[x].size())
                {
                    if(e[x][0]==1)
                    {
                        swap(dp[x][0][0],dp[x][0][1]);
                    }
                    else
                    {
                        swap(dp[x][1][0],dp[x][1][1]);
                    }
                }
                //printf("xx %I64d %I64d %I64d %I64d
    ",dp[x][0][0],dp[x][0][1],dp[x][1][0],dp[x][1][1]);
                long long a1=0,a0=0;
                
                //printf("%I64d %I64d
    ",ans1,ans0);
                a1=(dp[x][0][0]+dp[x][1][0])*ans1%mod+(dp[x][0][1]+dp[x][1][1])*ans0%mod;
                a0=(dp[x][0][0]+dp[x][1][0])*ans0%mod+(dp[x][0][1]+dp[x][1][1])*ans1%mod;
                ans1=a1%mod;
                ans0=a0%mod;
                //printf("%I64d %I64d
    ",ans1,ans0);
            }
        for(int i = 1;i <= m;i++)
            if(d[i]==2 && !vis[i])
            {
                cnt=0;
                dfs(i);
                dp[i][0][0]=1;
                dp[i][0][1]=0;
                dp[i][1][0]=0;
                dp[i][1][1]=0;
                for(int step = 2;step <= cnt;step++)
                    memset(dp[s[step]],0,sizeof(dp[s[step]]));
                for(int step = 1;step < cnt;step++)
                {
                    for(int ii = 0;ii < 2;ii++)
                        for(int jj = 0;jj < 2;jj++)
                            for(int kk = 0;kk < 2;kk++)
                            {
                                up(dp[s[step+1]][kk][((ii^fa[s[step]].a)|(kk^fa[s[step]].b))^jj],dp[s[step]][ii][jj]);
                            }
                }
                int x=s[cnt];
                for(int ii=0;ii<2;ii++)
                    if((ii^fa[x].a)|(fa[x].b))swap(dp[x][ii][0],dp[x][ii][1]);
                long long a1=0,a0=0;
                //printf("xx %I64d %I64d %I64d %I64d
    ",dp[x][0][0],dp[x][0][1],dp[x][1][0],dp[x][1][1]);
                a1+=(dp[x][0][0]+dp[x][1][0])*ans1%mod+(dp[x][0][1]+dp[x][1][1])*ans0%mod;
                a0+=(dp[x][0][0]+dp[x][1][0])*ans0%mod+(dp[x][0][1]+dp[x][1][1])*ans1%mod;
                
                dp[i][0][0]=0;
                dp[i][0][1]=0;
                dp[i][1][0]=1;
                dp[i][1][1]=0;
                for(int step = 2;step <= cnt;step++)
                    memset(dp[s[step]],0,sizeof(dp[s[step]]));
                for(int step = 1;step < cnt;step++)
                {
                    for(int ii = 0;ii < 2;ii++)
                        for(int jj = 0;jj < 2;jj++)
                            for(int kk = 0;kk < 2;kk++)
                            {
                                up(dp[s[step+1]][kk][((ii^fa[s[step]].a)|(kk^fa[s[step]].b))^jj],dp[s[step]][ii][jj]);
                            }
                }
                for(int ii=0;ii<2;ii++)
                    if((ii^fa[x].a)|(1^fa[x].b))swap(dp[x][ii][0],dp[x][ii][1]);
                //printf("xx %I64d %I64d %I64d %I64d
    ",dp[x][0][0],dp[x][0][1],dp[x][1][0],dp[x][1][1]);
                a1+=(dp[x][0][0]+dp[x][1][0])*ans1%mod+(dp[x][0][1]+dp[x][1][1])*ans0%mod;
                a0+=(dp[x][0][0]+dp[x][1][0])*ans0%mod+(dp[x][0][1]+dp[x][1][1])*ans1%mod;
                ans1=a1%mod;
                ans0=a0%mod;
                //printf("%I64d %I64d
    ",ans1,ans0);
            }
        for(int i = 1;i <= m;i++)
            if(!vis[i])ans1=ans1*2%mod;
        printf("%I64d
    ",ans1);
        return 0;
    }
    AC code
  • 相关阅读:
    Ubuntu若何开启root用户及此外登录成就的处置
    在Linux操作零碎中若何装配内核
    谭浩强C语身教程第一章C言语概述(1)
    Linux独霸琐细下文件的非凡权限
    关于C#中的String replace 函数
    Animation_01_2011年12月24日13:07:23
    HorizontalScrollView_应用举例
    res/values/colors.xml
    Text_01_2011年12月24日12:57:02
    rubbish
  • 原文地址:https://www.cnblogs.com/Randolph87/p/5920182.html
Copyright © 2020-2023  润新知