CF724G 【Xor-matic Number of the Graph】

  • 题目就不翻译了吧,应该写的很清楚了。。。
  • 首先 $,$ 不懂线性基的可以戳这里。知道了线性基$,$ 但是从来没有写过线性基和图论相结合的$,$ 可以戳这里
  • 好$,$ 点完了这些前置技能之后,我们就可以来愉快的切题啦!

正片$:$

  • 类比$[WC$ $2011]$ 最大$xor$和路径$,$ 我们肯定要找环$,$ 找完环后再用环去构造线性基$,$ 因为还是那句话嘛$:$ 任何一条复杂路径$,$ 都能有起始两点的一条简单路径再加上若干个环组成
  • 那么接下来的问题就是$:$如何求出亦或值的和?
  • $en$~~~,直接依据线性基,求出可以被这个线性基构造出的所有亦或值的和,然后相加,呃,是个好方法。
  • 可惜$,$ 很不幸$,$ $xor$不满足分配律。然后我又冥思苦想了2天,终于找到了“$n$个数中,任取几个数的亦或和的和”这个问题的$O(n6363)$的做法,高兴了好一阵子,然后发现。。。哎$,$ 现在想想还是难受啊。
  • 然后痛定思痛$,$ 改变视角——$woc$,原来这么简单$!$
  • 不再考虑每一对数的$xor$和,我们改变目标 $,$去求:对于每一对点的每一位,有多少种方案能使该位的$xor$和位1
  • 对于我们原先就求出来的$d[1]$到$d[n]$ $($就是各个点到1号点的一条简单路径的$xor$和$)$ $,$ 我们要想求出$u$到$v$的一条简单路径$,$ 只需要用$d[u]$ $xor$ $d[v]$即可$,$ 因为重复走到路径会因为$xor$操作而抵消掉。
  • 若线性基中有$cnt$个非零位,则一共会产生$2^{cnt}$个不同的$xor$值。
  • 知道了这些以后$,$ 我们就可以开始讨论了$:$
  • $1.$ $d[u]$ $xor$ $d[v]$第$k$位为1:这样的话,我们就需要不取第$k$个线性基$($因为只有第$k$位为1了才会对答案产生贡献嘛$!$ $)$ $,$ 这样的话,该项对于答案的贡献即为$:$ $2^{k}*2^{cnt-1}$。

$2.$ $d[u]$ $xor$ $d[v]$第$k$位为0$:$ 显然,一定要取$k$个线性基$,$ 对答案的贡献即为$:$ $2^k*2^{cnt-1}$。

  • 尽管这样$,$ 时间复杂度依然是$O(n^2*63)$的$,$ 吃不消$,$ 那么哪里还有优化的空间呢$?$
  • 注意到$,$ $d[i]$第$k$位的值是固定的$,$ 那么我们就可以不单独讨论$"d[u]$ xor $d[v]"$对于答案的贡献$,$ 直接讨论$d[u]$对于答案的贡献。
  • 先统计出第$k$位为$0$的数的个数$,$ 我们将其记为$x$ $,$ 再统计出第$k$位为$1$的数的个数$,$ 记为$y$ $,$ 总共有$point$个点。
  • 分为$4$种情况讨论$:$
  • $1.$ $d[i]$的第$k$位为$1$ $,$ 线性基中有第$k$位为$1$的数$:$ 此时我们有两种选择:$a.$ 选线性基中的$,$ 另一个点选择第$k$位为$0$的。 $b.$ 不选线性基中的$,$ 另一个点选择第$k$位为$1$的。总体对于答案的贡献为:$2^k2^{cnt-1}(point-1)$ $,$ 减$1$就是为了把自己给去掉。

$2.$ $d[i]$的第$k$位为$1$ $,$ 线性基中没有第$k$位为$1$的数$:$ 这个时候另一个点只能取第$k$位为$0$的$,$ 所以总贡献为$:$ $2^k2^{cnt}x$。

$3.$ $d[i]$的第$k$位为$0$ $,$ 线性基中有第$k$位为$1$的数$:$ 一样的$,$ 两种选择$:$ $a.$ 选线性基中的$,$ 另一个点选择第$k$位为$0$的。 $b.$ 不选线性基中的$,$ 另一个点选择第$k$位为$1$的。总贡献为$:$ $2^k2^{cnt-1}(point-1)$。

$3.$ $d[i]$的第$k$位为$0$ $,$ 线性基中没有第$k$位为$1$的数$:$ 另一个点只能取第$k$位为$1$的$,$ 总贡献$:$ $2^k2^{cnt}y$。

  • 最后别忘记给答案除个$2$就$OK$啦$!($要用逆元哦$)$

代码$:$

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=100005,M=400005,p=1e9+7,inv=500000004;
ll b[65],dist[M],d[N],a[N],two[65],s[N],z,ans,cnt,point;
int head[N],vet[M],nxt[M],c[65],n,m,x,y,tot;
bool vis[N],used[M];
void add(int x,int y,ll z){
    nxt[++tot]=head[x];
    vet[tot]=y;
    head[x]=tot;
    dist[tot]=z;
}
void insert(ll x){
    for (int i=62;i>=0;i--)
        if (x>>i)
            if (b[i]) x^=b[i];
            else {b[i]=x; break;}
}
void dfs(int u){
    a[++point]=d[u]; vis[u]=true;
    for (int i=head[u];i;i=nxt[i]){
        int v=vet[i];
        if (!vis[v]){
            d[v]=d[u]^dist[i];
            dfs(v);
        } else
            if (!used[i^1]){
                used[i^1]=true;
                insert(d[u]^d[v]^dist[i]);
            }
    }
}
ll calc(){
    ll ans=0;
    for (int j=0;j<=62;j++){
        ll x=0,y=0,flag=0;
        for (int i=1;i<=point;i++)
            if (a[i]>>j&1) x++; else y++;
        for (int i=0;i<=62;i++)
            if (b[i]>>j&1) flag=1;
        for (int i=1;i<=point;i++)
            if (a[i]>>j&1)
                if (flag)
                    (ans+=two[cnt-1]*(ll)(point-1)%p*two[j]%p)%=p;
                else
                    (ans+=two[cnt]*y%p*two[j]%p)%=p;
            else
                if (flag)
                    (ans+=two[cnt-1]*(ll)(point-1)%p*two[j]%p)%=p;
                else
                    (ans+=two[cnt]*x%p*two[j]%p)%=p;
    }
    return ans;
}
int main(){
    scanf("%d %d",&n,&m); tot=1;
    for (int i=1;i<=m;i++){
        scanf("%d %d %lld",&x,&y,&z);
        add(x,y,z); add(y,x,z);
    }
    two[0]=1;
    for (int i=1;i<=64;i++)
        two[i]=two[i-1]*2%p;
    for (int i=1;i<=n;i++)
        if (!vis[i]){
            memset(b,0,sizeof(b));
            memset(c,0,sizeof(c));
            point=0,cnt=0;
            dfs(i);
            for (int j=0;j<=62;j++) cnt+=(b[j]>0);
            (ans+=calc())%=p;
        }
        ans=ans*inv%p;
        printf("%lld\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/WR-Eternity/p/10291631.html

时间: 2024-10-01 14:46:24

CF724G 【Xor-matic Number of the Graph】的相关文章

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,

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

724G - Xor-matic Number of the Graph 题意: 待补~~ 参考http://www.cnblogs.com/ljh2000-jump/p/6443189.html

【LeetCode-面试算法经典-Java实现】【009-Palindrome Number(回文数)】

[009-Palindrome Number(回文数)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Determine whether an integer is a palindrome. Do this without extra space. 题目大意 判断一个数字是否是回访字数,不要使用额外的空间. 解题思路 为了不使用额外的空间,参考了其它的解决,那些解法看起来在isPalindrome方法中没有使用额外参数,但是却使用了方法调用,这个比一个整数消耗的

【LeetCode-面试算法经典-Java实现】【136-Single Number(只出现一次的数字)】

[136-Single Number(只出现一次的数字)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Given an array of integers, every element appears twice except for one. Find that single one. Note: Your algorithm should have a linear runtime complexity. Could you implement it wit

【LeetCode-面试算法经典-Java实现】【137-Single Number II(只字出一次的数字II)】

[137-Single Number II(只出现一次的数字II)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Given an array of integers, every element appears three times except for one. Find that single one. Note: Your algorithm should have a linear runtime complexity. Could you imple

【LeetCode-面试算法经典-Java实现】【017-Letter Combinations of a Phone Number (电话号码上的单词组合)】

[017-Letter Combinations of a Phone Number (电话号码上的单词组合)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Given a digit string, return all possible letter combinations that the number could represent. A mapping of digit to letters (just like on the telephone bu

【LeetCode-面试算法经典-Java实现】【202-Happy Number(开心数字)】

[202-Happy Number(开心数字)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 代码下载[https://github.com/Wang-Jun-Chao] 原题 Write an algorithm to determine if a number is "happy". A happy number is a number defined by the following process: Starting with any positive

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

【从零学习经典算法系列】分治策略实例——二分查找

1.二分查找算法简介 二分查找算法是一种在有序数组中查找某一特定元素的搜索算法.搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束:如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较.如果在某一步骤数组 为空,则代表找不到.这种搜索算法每一次比较都使搜索范围缩小一半.折半搜索每次把搜索区域减少一半,时间复杂度为Ο(logn). 二分查找的优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且