zoukankan      html  css  js  c++  java
  • lg5169 xtq的异或和

    题目

    根据一些众所周知的结论,我们先跑一棵生成树出来,之后把所有简单环都搞出来,那么(u)(v)的路径一定可以由树上的路径和一些简单环拼起来得到

    把所有简单环都插到一个线性基里,之后dfs一下线性基求出这些环能拼出的异或和有哪些;

    再求一下树上的异或前缀和,(u)(v)的路径一定是(pre_uigoplus pre_v)再异或上一些环构成的

    开两个桶,(A[i])表示前缀异或和为(i)的点得个数,(B[i])表示(i)是否能被线性基凑出来,于是答案就是(A imes A imes B),自然是异或卷积,于是大力fwt就好了

    代码

    #include<bits/stdc++.h>
    #define re register
    #define LL long long
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    const int maxn=1e5+5;
    const int len=262144;
    struct E{int v,nxt,w;}e[maxn<<1];
    int fa[maxn],n,m,q,head[maxn],num,vis[maxn],u[maxn*3],v[maxn*3],va[maxn*3],pre[maxn],M;
    int lb[18];LL tax[len],tmp[len];
    inline int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
    inline void add(int x,int y,int w) {
    	e[++num].v=y;e[num].nxt=head[x];head[x]=num;e[num].w=w;
    }
    void dfs(int x) {
    	vis[x]=1;
    	for(re int i=head[x];i;i=e[i].nxt) {
    		if(vis[e[i].v]) continue;
    		pre[e[i].v]=pre[x]^e[i].w;
    		dfs(e[i].v);
    	}
    }
    inline void ins(int x) {
    	for(re int i=17;i>=0;--i)
    		if(x>>i&1) {
    			if(!lb[i]) {lb[i]=x;return;}
    			x^=lb[i];
    		}
    }
    void Dfs(int bit,int nw) {
    	if(bit==-1) {
    		tmp[nw]=1;return;
    	}
    	Dfs(bit-1,nw);
    	if(lb[bit]) Dfs(bit-1,nw^lb[bit]);
    }
    inline void Fwt(LL *f,int o) {
    	for(re int i=2;i<=len;i<<=1)
    		for(re int ln=i>>1,l=0;l<len;l+=i)
    			for(re int x=l;x<l+ln;++x) {
    				LL g=f[x],h=f[x+ln];
    				f[x]=g+h,f[x+ln]=g-h;
    				if(o==-1) f[x]>>=1ll,f[x+ln]>>=1ll;
    			}
    }
    int main() {
    	n=read(),m=read(),q=read();
    	for(re int i=1;i<=n;i++) fa[i]=i;
    	for(re int x,y,w,i=1;i<=m;i++) {
    		x=read(),y=read(),w=read();
    		int xx=find(x),yy=find(y);
    		if(xx==yy) {u[++M]=x,v[M]=y,va[M]=w;continue;}
    		fa[xx]=yy,add(x,y,w),add(y,x,w);
    	}
    	for(re int i=1;i<=n;i++) if(!vis[i]) dfs(i);
    	for(re int i=1;i<=M;i++) ins(pre[u[i]]^pre[v[i]]^va[i]);
    	for(re int i=1;i<=n;i++) tax[pre[i]]++;
    	Dfs(17,0);Fwt(tax,1),Fwt(tmp,1);
    	for(re int i=0;i<len;i++) tax[i]=tax[i]*tax[i]*tmp[i];
    	Fwt(tax,-1);
    	for(re int x;q;--q) printf("%lld
    ",tax[x=read()]);
    	return 0;
    }
    
  • 相关阅读:
    L3-001. 凑零钱(深度优先搜索)
    L2-008. 最长对称子串
    java里面求交集并集补集
    eclipse里面ctrl+T查看继承树,左边的这些绿色红色,F,S,C代表什么意思
    树的遍历(已知前序遍历中序遍历求后序遍历,或者已知后序中序求先序)
    L1-009. N个数求和
    面试题系列之---【MySql事务隔离级别】
    我爱java系列---【待定】
    我爱java系列之---【商城项目微服务鉴权代码实现(二)—JWT在项目中的应用案例】
    我爱java系列之---【JWT实现微服务鉴权(一)】
  • 原文地址:https://www.cnblogs.com/asuldb/p/12005678.html
Copyright © 2011-2022 走看看