CodeForces - 704C

题目大意:给你一个逻辑表达式,然后让你计算表达式为真的取值情况数,表达式由一系列的 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\n",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\n",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\n",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\n",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\n",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\n",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\n",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\n",ans1,ans0);
        }
    for(int i = 1;i <= m;i++)
        if(!vis[i])ans1=ans1*2%mod;
    printf("%I64d\n",ans1);
    return 0;
}
AC code

 

posted @ 2016-09-29 15:52  Randolph87  阅读(468)  评论(0编辑  收藏  举报