其他分享
首页 > 其他分享> > 习题:Network Safety(冰茶姬)

习题:Network Safety(冰茶姬)

作者:互联网

题目

传送门

思路

考虑如果不安全则一定满足式子\(a\oplus x=b\),移项之后直接\(a\oplus b=x\)

也就是指a和b的状态一定是一样的,即要么都异或,要么都不异或,对其进行冰茶姬的合并

对于同一个x,方案数直接是\(2^{cnt}\),cnt表示冰茶姬数量

对于其他的,即没有点权异或起来为x的x,也是很好算的,直接剩余x的数量乘上\(2^n\)

代码

#include<iostream>
#include<vector>
#include<map>
using namespace std;
const int mod=1e9+7;
namespace IO
{
    void read(int &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void read(long long &x)
    {
        x=0;
        int f=1;
        char c=getchar();
        while('0'>c||c>'9')
        {
            if(c=='-')
                f=-1;
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=(x<<3)+(x<<1)+c-'0';
            c=getchar();
        }
        x*=f;
    }
    void write(int x)
    {
        if(x<10)
            putchar(x%10+'0');
        else
        {
            write(x/10);
            putchar(x%10+'0');
        }
    }
    void write(long long x)
    {
        if(x<10)
            putchar(x%10+'0');
        else
        {
            write(x/10);
            putchar(x%10+'0');
        }
    }
}
namespace ufs
{
    int tot;
    int fa[1000005];
    void makeset(int n)
    {
        tot=n;
        for(int i=1;i<=n;i++)
            fa[i]=i;
    }
    int findset(int x)
    {
        if(x==fa[x])
            return x;
        return fa[x]=findset(fa[x]);
    }
    void merge(int u,int v)
    {
        int a=findset(u);
        int b=findset(v);
        if(a==b)
            return;
        tot--;
        fa[a]=b;
    }
}
using namespace IO;
using namespace ufs;
struct edge
{
    int u,v;
};
int n,m;
int cnt;
long long limit,ans;
long long c[500005];
map<long long,int> hashh;
vector<int> g[500005];
vector<edge> w[500005];
long long qkpow(int a,long long b)
{
    if(b==0)
        return 1;
    if(b==1)
        return a;
    long long t=qkpow(a,b/2);
    t=t*t%mod;
    if(b%2==1)
        t=t*a%mod;
    return t;
}
int main()
{
	read(n);
    read(m);
    read(limit);
    makeset(n);
    limit=qkpow(2,limit);
    for(int i=1;i<=n;i++)
        read(c[i]);
    for(int i=1,u,v;i<=m;i++)
    {
        read(u);
        read(v);
        g[u].push_back(v);
        g[v].push_back(u);
	}
    for(int i=1;i<=n;i++)
        for(int j=0;j<g[i].size();j++)
            if(hashh.count(c[i]^c[g[i][j]])==0)
                hashh[c[i]^c[g[i][j]]]=++cnt;
    for(int i=1;i<=n;i++)
        for(int j=0;j<g[i].size();j++)
            w[hashh[c[i]^c[g[i][j]]]].push_back((edge){i,g[i][j]});
    limit-=cnt;
    for(int i=1;i<=cnt;i++)
    {
        for(int j=0;j<w[i].size();j++)
            merge(w[i][j].u,w[i][j].v);
        ans=(ans+qkpow(2,tot))%mod;
        for(int j=0;j<w[i].size();j++)
        {
            fa[w[i][j].u]=w[i][j].u;
            fa[w[i][j].v]=w[i][j].v;
        }
        tot=n;
    }
    ans=(ans+limit*qkpow(2,n)%mod)%mod;
    write(ans);
    return 0;
}

标签:冰茶,int,异或,long,read,while,Safety,习题
来源: https://www.cnblogs.com/loney-s/p/13552834.html