CF1466F Euclid's nightmare 题解

题意

你有\(n\)\(m\)维的向量,保证每个向量最多只有两维是\(1\),其他的都是\(0\),你可以从这些向量中挑选若干个向量做模\(2\)意义下的加法,现在请你求出,通过这种加法,能得到多少本质不同的向量。同时,请你求出最小的向量数,使得这些向量能凑出所有能得到的向量。

分析

其实只看一眼还是没有多大思路,但是发现,一个维度要么是\(1\)要么是\(0\),所以对于某一维度,如果它已经是\(1\)了,那么它再被加一次就会回到\(0\),而开始的时候这个维度就是\(0\),所以对这个维度单独来说,是经过了\(0->1->0\)的这个过程,我们抽象的考虑一下,就是形成了一个环。所以对于那些只有一维是\(1\)的向量,我们可以考虑,把每一维都看成一个单独的点,另外再外加一个起点表示所有的维度都是\(0\),那么如果有两个这一维是\(1\)的向量,就会连成一个环,而如果出现了一个环,那么这个环中至少有一个向量是可以被代替的。然后考有两个维度是\(1\)的向量的情况,由于向量的坐标没有负数,所以能形成环的情况只有通过某个向量使得某一维度变成\(0\)与之前的某个向量相等,那么这个也可以发现是有环的情况,对于这样一个向量,我们可以把它两个为\(1\)的维度连起来,如果有一维之前被单独加过,并且另一维也被单独加过的话,那么这条边就会形成一个长度为\(3\)的环,这和之前一维的推理情况一致,我们可以不加这个向量,因为这个向量的两端之前都可以独立的达到\(0\)或者\(1\)了。
所以我们的做法就是,把\(m\)个维度都单独看成一个点,同时多加一个原点表示\(0\),对于一个大小为\(1\)的向量,我们把\(0\)和它有值的那一维连边,对于大小为\(2\)的向量,我们把它有值的两维连边,可以发现,如果不存在环,那么无论怎么样选择向量相加,得到的结果向量都一定不会重复,那么最后的答案就是\(2^n\),但是有一些向量加进去之后会形成环,所以我们可以用并查集来维护,如果一个向量连边后会形成环,那么我们就放弃这个向量,最后我们记成功加进去的向量数为\(cnt\),那么答案就是\(2^{cnt}\)

代码


#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int father[N];
int find(int x){
    if(father[x]!=x)
        father[x]=find(father[x]);
    return father[x];
}
const int P=1e9+7;
inline int ksm(int x,int y){
    int res=1;
    while(y){
        if(y&1)
            res=1ll*res*x%P;
        x=1ll*x*x%P;
        y>>=1;
    }
    return res%P;
}
int main(void){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=0;i<=m;i++)
        father[i]=i;
    int cnt=0;
    vector<int>ans(n+1);
    for(int i=1;i<=n;i++){
        int k,d1;
        scanf("%d%d",&k,&d1);
        if(k==1){
            int l=find(0),r=find(d1);
            if(l!=r){
                father[l]=r;
                ans[++cnt]=i;
            }
        }
        else {
            int d2;
            scanf("%d",&d2);
            int l=find(d1),r=find(d2);
            if(l!=r){
                father[l]=r;
                ans[++cnt]=i;
            }
        }
    }
    printf("%d %d\n",ksm(2,cnt),cnt);
    for(int i=1;i<=cnt;i++)
        printf("%d ",ans[i]);
    return 0;
}

心得

发现这些维度是在模二意义下的加法,一个维度如果被加超过两次就会回到原样,所以其实可以联想到这个维度如果被加了两条边,那么这个维度就相当于不存在了,而如果一个集合中的所有元素都被连了两条边,那么这个集合也相当于不存在了,而一个集合中的点都有两条边,这显然是一个环,所以可以联想到要怎么加边才能避免环的出现。
可以算是经典的从数学到图论到模型转换吧,还是不是很熟悉,要多做一些题了。

posted @ 2021-10-20 10:45  兮水XiShui  阅读(80)  评论(0)    收藏  举报