频道澳门葡京手机版网址
登录注册
澳门葡京手机版网址 > 澳门葡京手机版网址 > 综合编程 > 其他综合 > 正文
【WC模拟】Equation
2017-01-20 09:56:30         来源:时光真疯狂, 我一路执迷于匆忙.   
收藏   我要投稿

Description

这里写图片描述

n,m<=10^5

Solution

考虑图论转化,既然每个变量最多只会出现两次,那么大家把出现两次的变量所在的or组看做点,每个出现两次的变量看做边,边权视这两个变量是否相同而定。(0或1)

根据题目条件大家每个点的度数最多为2,也就是只会出现环和链。

设Fi,j,k表示当前做到第i个点,异或值为j,上一位填的是k的方案数,转移显然。

最后分类讨论一下就行了,注意特判自环和没有出现的点。

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define rep(i,a) for(int i=last[a];i;i=next[i])
using namespace std;
typedef long long ll;
const int N=1e5+5,mo=1e9+7;
int n,m,l,x,y,ans,a[N][2],r[N],p[N],w[N];
int t[N*2],next[N*2],v[N*2],one[N],last[N];
int f[N][2][2],now[2],s[2],la[2];
bool bz[N];
void add(int x,int y,int z) {
    t[++l]=y;v[l]=z;next[l]=last[x];last[x]=l;
}
void dfs(int x,int y) {
    if (bz[x]) return;
    bz[x]=1;w[++w[0]]=x;
    rep(i,x) 
        if (t[i]!=y) {
            p[++p[0]]=v[i];
            dfs(t[i],x);            
        }
}
void dp_chain() {
    memset(f[1],0,sizeof(f[1]));
    if (one[w[1]]) f[1][1][1]=2,f[1][1][0]=f[1][0][0]=1;
    else f[1][1][1]=f[1][0][0]=1;
    fo(i,1,w[0]-1) {
        fo(j,0,1) 
            fo(k,0,1) 
                f[i+1][j][k]=0;
        fo(j,0,1)
            fo(k,0,1) 
                if (f[i][j][k]) 
                    fo(l,0,1) 
                        (f[i+1][j^(l|(p[i]^k))][l]+=f[i][j][k])%=mo;
    }
    s[0]=s[1]=0;
    la[0]=now[0];la[1]=now[1];
    if (one[w[w[0]]]) {
        fo(i,0,1) 
            fo(j,0,1)
                (s[i]+=f[w[0]][i][j])%=mo;
    } else fo(i,0,1) s[i]=f[w[0]][i][0];
    now[0]=((ll)la[0]*s[0]%mo+(ll)la[1]*s[1]%mo)%mo;
    now[1]=((ll)la[0]*s[1]%mo+(ll)la[1]*s[0]%mo)%mo;
}   
void dp_circle() {
    s[0]=s[1]=0;
    la[0]=now[0];la[1]=now[1];
    if (w[0]==1) {
        if (p[0]) s[p[1]]=2;
        else {
            if (one[w[1]]==1) s[0]=s[1]=1;
            else s[0]=1,s[1]=3;
        }
        now[0]=((ll)la[0]*s[0]%mo+(ll)la[1]*s[1]%mo)%mo;
        now[1]=((ll)la[0]*s[1]%mo+(ll)la[1]*s[0]%mo)%mo;
        return;
    }
    fo(st,0,1) {
        memset(f[1],0,sizeof(f[1]));
        if (st) f[1][1][0]=f[1][1][1]=1;
        else f[1][0][0]=f[1][1][1]=1;
        fo(i,1,w[0]-1) {
            fo(j,0,1) 
                fo(k,0,1) 
                    f[i+1][j][k]=0;
            fo(j,0,1)   
                fo(k,0,1) 
                    if (f[i][j][k]) 
                        fo(l,0,1) 
                            (f[i+1][j^(l|(p[i]^k))][l]+=f[i][j][k])%=mo;
        }
        int en=st^p[p[0]];
        fo(i,0,1) (s[i]+=f[w[0]][i][en])%=mo;
    }
    now[0]=((ll)la[0]*s[0]%mo+(ll)la[1]*s[1]%mo)%mo;
    now[1]=((ll)la[0]*s[1]%mo+(ll)la[1]*s[0]%mo)%mo;
}
int main() {
    freopen("equation.in","r",stdin);
    freopen("equation.out","w",stdout);
    scanf("%d%d",&n,&m);
    fo(i,1,n)
        for(scanf("%d",&y);y;y--) {
            scanf("%d",&x);
            if (!a[abs(x)][0]) a[abs(x)][0]=i*((x>0)?1:-1);
            else a[abs(x)][1]=i*((x>0)?1:-1);
        }
    ans=now[0]=1;
    fo(i,1,m) {
        if (!a[i][0]) {ans=ans*2%mo;continue;}
        if (!a[i][1]) {one[abs(a[i][0])]++;continue;}
        int x=a[i][0],y=a[i][1],z=x<0&&y>0||x>0&&y<0;
        add(abs(x),abs(y),z);add(abs(y),abs(x),z);
        r[abs(x)]++;r[abs(y)]++;
    }
    fo(i,1,n) 
        if (r[i]==1&&!bz[i]) {
            p[0]=w[0]=0;
            dfs(i,0);
            dp_chain();
        }
    fo(i,1,n) 
        if (!bz[i]) {
            p[0]=w[0]=0;
            dfs(i,0);
            dp_circle();
        }
    printf("%lld\n",(ll)ans*now[1]%mo);
}
点击复制链接 与好友分享!回澳门葡京手机版网址澳门葡京手机版网址
上一篇:Codeforces 8VC Venture Cup 2017 - Elimination Round
下一篇:App微信支付 php后台接口
相关文章
图文推荐
点击排行

关于大家 | 联系大家 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 澳门葡京手机版网址_澳门新莆京娱乐_www.88807.com - 点此进入--致力于做实用的IT技术学习网站

XML 地图 | Sitemap 地图