• bzoj1553: XOR网络


    Description

      计算给定范围内有多少种输入可以使输出为1。 我们假设3 < n < 100, 3 < m < 3000,而且网络中的门是用1到m之间的数任意编号的。

    Input

    文件第一行包含三个整数,分别表示输入的个数,门的个数,连接到输出的门的编号。以下的m行描述网络中的连接情况。第I行表示第I个门的两个输入,两个输入为范围[-n,m]之间的一个整数。如果输入是网络的第k个输入,则连接的描述是一个整数-k,如果输入是第j个门,则连接的描述是一个整数j。以下两行各有一个n位二进制串,表示输入的上限和下限。

    Output

    包含一个整数,表示给定范围内有多少种输入可以使输出为1。
    由异或的性质,拓扑排序并处理出最终输出等于哪些输入异或起来,于是转成区间内有几个二进制数和指定数的按位与有奇数个1,可以数位dp
    #include<cstdio>
    #include<bitset>
    typedef unsigned long long u64;
    int n,m,o;
    int es[6007],enx[6007],e0[3007],deg[3007],q[3007],ql=0,qr=0,ep=2;
    std::bitset<102>st[3007];
    int S[107];
    char l[107],r[107];
    void ae(int a,int b){
        es[ep]=b;enx[ep]=e0[a];e0[a]=ep++;
        ++deg[b];
    }
    struct num{
        u64 a,b;
        num(u64 _a,u64 _b):a(_a),b(_b){};
        num(u64 _a=0):a(0),b(_a){}
        void print(){
            int ss[107],sp=0;
            u64 v1=a>>32,v2=a&0xffffffffll;
            u64 v3=b>>32,v4=b&0xffffffffll;
            while(v1|v2|v3|v4){
                v2+=v1%10<<32;v1/=10;
                v3+=v2%10<<32;v2/=10;
                v4+=v3%10<<32;v3/=10;
                ss[sp++]=v4%10;v4/=10;
            }
            if(!sp)putchar('0');
            while(sp)putchar('0'+ss[--sp]);
        }
    };
    num operator+(num x,num y){
        u64 c=x.b+y.b;
        return num(x.a+y.a+(c<x.b),x.b+y.b);
    }
    num operator-(num x,num y){
        return num(x.a-y.a-(x.b<y.b),x.b-y.b);
    }
    num f[107][2][2];
    void pre(){
        f[n+1][0][0]=1;
        for(int i=n;i;--i){
            f[i][0][0]=f[i][1][S[i]]=f[i+1][0][0]+f[i+1][1][0];
            f[i][0][1]=f[i][1][S[i]^1]=f[i+1][0][1]+f[i+1][1][1];
        }
    }
    num cal(char*s,bool e){
        for(int i=1;i<=n;++i)s[i]-='0';
        int d=0;
        num ans=0;
        for(int i=1;i<=n;++i){
            if(s[i])ans=ans+f[i][0][d^1];
            if(S[i])d^=s[i];
        }
        if(e){
            int d=0;
            for(int i=1;i<=n;++i)if(S[i])d^=s[i];
            ans=ans+d;
        }
        return ans;
    }
    int main(){
        scanf("%d%d%d",&n,&m,&o);
        for(int i=1,a,b;i<=m;++i){
            scanf("%d%d",&a,&b);
            if(a<0)st[i].flip(-a);
            else ae(a,i);
            if(b<0)st[i].flip(-b);
            else ae(b,i);
        }
        for(int i=1;i<=m;++i)if(!deg[i])q[++qr]=i;
        while(ql!=qr){
            int w=q[++ql];
            for(int i=e0[w];i;i=enx[i]){
                int u=es[i];
                st[u]^=st[w];
                if(!--deg[u])q[++qr]=u;
            }
        }
        for(int i=1;i<=n;++i)S[i]=st[o][i];
        scanf("%s%s",l+1,r+1);
        pre();
        (cal(r,1)-cal(l,0)).print();
        return 0;
    }
  • 相关阅读:
    计算机网络技术基础2
    java基础
    跨页传递参数或临时表的几种方法
    ASP.NET2.0文件上传以及图片处理总结篇 [转]
    正则表达式
    ASP.NET2.0中WEB应用程序的部署
    比较著名的.net技术论坛名称
    WordPress 插件开发实例 – 详细注释的 Widget 开发例子
    Java Applet签名验证
    Java Logging API Tutorial
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6254189.html
Copyright © 2020-2023  润新知