Codeforces 724 G Xor-matic Number of the Graph 线性基+DFS

G. Xor-matic Number of the Graph

http://codeforces.com/problemset/problem/724/G

题意:给你一张无向图。定义一个无序三元组(u,v,s)表示u到v的(不一定为简单路径)路径上xor值为s。求出这张无向图所有不重复三元组的s之和。1≤n≤10^5,1≤m≤2*10^5。

想法:

如果做过【Wc2011 xor】这道题目(题解),那么问题变得简单起来了。

①假设我们钦定一个(u,v),设任意一条u->v的路径xor值为X,该连通图所有小环xor值构成的序列为{Ai}。

那么(u,v)的所有路径的xor值可以由X xor {Ai}的子集xor值得到。于是一个(u,v)的 s 之和变成了求X xor{Ai}的子集可以得到多少个不同的数,这些不同的数的和是多少?

如果能知道{Ai}的子集xor值的值域,那么好办了。于是用线性基得到值域{T}。求和的话,按位考虑定义S(i)为{T}中第i为1的个数,为0的个数取个补集就好了。

对于一个(u,v):

②考虑所有的无序点对(u,v)的答案。上面说过任意一条u->v的路径都可以,不如就钦定是DFS遍历得到DFS树的树上路径。

树上两点路径xor值的求法很简单:设dis(i)表示第i个到根节点路径xor值。

dis(a,b)=dis(a) xor dis(lca(a,b)) xor dis(b) xor dis(lca(a,b))=dia(a) xor dis(b)。

根据上面求ans 的式子,ans只与X的第j位是什么有关,所以设cnt(i)表示两点路径xor值第i位为1的个数。cnt(i)可以利用上面dis(a,b)=dia(a) xor dis(b)求。

对于所有(u,v):

于是解决了。

#include<cstdio>
#include<vector>
#define ll long long
const int len(100000),MP(1000000007);
struct Node{int nd;ll co;};
std::vector<Node>Edge[len+10];
int n,m,u,v,top,ans,much,vis[len+10];
ll sum,S[61],cnt[61],now[61];//cnt(i) 统计 i-th =0的个数 now(i):dx^dy i-th==1的个数
ll st[len+10],dis[len+10],All,t;
struct Base_Linear
{
    ll p[61];int size;
    void ins(ll x)
    {
        for(int j=60;j>=0;j--)
        if((x>>j)&1)
        {
            if(p[j])x^=p[j];
            else {p[j]=x;size++;break;}
        }
    }
}BL;
template <class T>void read(T &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){f=(ch==‘-‘);ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    x=f?-x:x;
}
ll power(int a,int b)
{
    ll t=1,y=a;
    for(;b;b>>=1)
    {
        if(b&1)t=(t*y)%MP;
        y=(y*y)%MP;
    }
    return t;
}
void add(int a,int b,ll c){Edge[a].push_back((Node){b,c});}
void plus(ll x)
{
    for(int j=0;j<=60;j++)
    if(((x>>j)&1)==0)cnt[j]++;
}
void Dfs(int x)
{
    much++; vis[x]=1; plus(dis[x]); st[++top]=dis[x];
    for(int v=0,sz=Edge[x].size();v<sz;v++)
    {
        Node y=Edge[x][v];
        if(vis[y.nd])BL.ins(dis[x]^dis[y.nd]^y.co);
        else
        {
            dis[y.nd]=dis[x]^y.co;
            Dfs(y.nd);
        }
    }
}
void Back()
{
    for(int j=0;j<=60;j++)cnt[j]=now[j]=S[j]=0;
    for(int j=0;j<=60;j++)BL.p[j]=0; BL.size=0;
    much=0; All=0;
}
void Total()
{
    for(;top;top--)
    {
        for(int j=0;st[top];j++,st[top]>>=1)
        if(st[top]&1)now[j]=(now[j]+cnt[j])%MP;
    }
    for(int j=0;j<=60;j++)All|=BL.p[j];
    for(int j=0;All;j++,All>>=1)
    if(All&1)S[j]=power(2,BL.size-1);
    All=power(2,BL.size); ll C=1;
    for(int j=0;j<=60;j++,C<<=1,C%=MP)
    {
        sum=(ll)much*(much-1)/2;
        ll t1=now[j]*(All-S[j])%MP;
        ll t2=((sum-now[j])*S[j])%MP;
        ans=(ans+C*t1+C*t2)%MP;
    }
}
int main()
{
    read(n),read(m);
    for(int i=1;i<=m;i++)
    {
        read(u),read(v),read(t);
        add(u,v,t),add(v,u,t);
    }
    for(int i=1;i<=n;i++)
    if(!vis[i])//图可能不连通
    {
        Back();
        Dfs(i);
        Total();
    }
    ans+=ans<0?MP:0;
    printf("%d",ans);
    return 0;
}

时间: 2024-08-27 22:57:06

Codeforces 724 G Xor-matic Number of the Graph 线性基+DFS的相关文章

Intel Code Challenge Final Round (Div. 1 + Div. 2, Combined) G - Xor-matic Number of the Graph 线性基好题

G - Xor-matic Number of the Graph 上一道题的加强版本,对于每个联通块需要按位算贡献. #include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PII pair<int, int> #define PLI pair<LL, int> #define ull unsigned lo

CF.724G.Xor-matic Number of the Graph(线性基)

题目链接 \(Description\) 给定一张带边权无向图.若存在u->v的一条路径使得经过边的边权异或和为s(边权计算多次),则称(u,v,s)为interesting triple. 求图中所有interesting triple中s的和. \(Solution\) 同[WC2011]Xor,任意两点路径的Xor和是它们间(任意一条)简单路径的和Xor一些环的和.so可以先处理出环上的和,构造线性基.两点间的一条简单路径可以直接求个到根节点的dis[]. 有了各点的dis,然后考虑用组合

【BZOJ-2115】Xor 线性基 + DFS

2115: [Wc2011] Xor Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 2142  Solved: 893[Submit][Status][Discuss] Description Input 第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si 与Ti之间存在 一条权值为 Di的无向边. 图中可能有重边或自环. Output 仅包含一个整数,表示最大

2115: [Wc2011] Xor (线性基+dfs)

2115: [Wc2011] Xor Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 5714  Solved: 2420 题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2115 Description: Input: 第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si 与Ti之间存在 一条权值为 Di

bzoj2115 [Wc2011] Xor——高斯消元 &amp; 异或线性基

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2115 异或两次同一段路径的权值,就相当于没有走这段路径: 由此可以得到启发,对于不同的走法,也许只需要找出一些东西,就可以把所有的走法用它们来异或表示出来: 再关注图上的环路,因为从 1 到 n 的不同路径也可以看作是经由 1 和 n 连接的环路,路径上也可能有环路: 发现对于环路的不同走法,就是把路与环的权值异或求最优值,重叠的部分异或了两次相当于不走: 于是问题转化为找出图上的所有环(

CodeForces - 724G Xor-matic Number of the Graph

Discription You are given an undirected graph, constisting of n vertices and m edges. Each edge of the graph has some non-negative integer written on it. Let's call a triple (u,?v,?s) interesting, if 1?≤?u?<?v?≤?n and there is a path (possibly non-si

CodeForces 1325E - Ehab&#39;s REAL Number Theory Problem【质因子+】

题意: ??给定一个数组 \(a\) ,数组中任意一个元素的因子数不超过 \(7\) ,找出一个最短的子序列,满足该子序列之积为完全平方数.输出其长度. 数据范围:\(1≤n≤10^5,1≤a_i≤10^6\) 分析: ??首先,对于数组中的每个元素,如果其因子中包含有一个完全平方数,那么可以把该完全平方数除去,不影响最后的结果. ??然后,可以发现,当一个数的因子个数 \(\leq 7\) 时,其包含的质因子个数 \(\leq 2\).(如果有3个质因子,那么至少有 \(8\) 个因子)当我们

CF724G. Xor-matic Number of the Graph

题意 http://codeforces.com/contest/724/problem/G 定义三元组\((u,v,s)(u<v)\):\(u\)到\(v\)的路径的\(xor\)和为\(s\)(可以不是简单路径),\((u,v,s)\)不同当且仅当\(u,v,s\)的其中一个参数不同. 求所有不同三元组的\(s\)值之和. \(n \in [1,10^5],m\in [0, 2\cdot 10^5], w\in [0,10^{18}]\) 题解 显然在同个联通块中,当前联通块中的所有环都可以

HDU3949 XOR(线性基第k小)

Problem Description XOR is a kind of bit operator, we define that as follow: for two binary base number A and B, let C=A XOR B, then for each bit of C, we can get its value by check the digit of corresponding position in A and B. And for each digit,