lg5169 xtq的异或和

题目

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

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

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

开两个桶,\(A[i]\)表示前缀异或和为\(i\)的点得个数,\(B[i]\)表示\(i\)是否能被线性基凑出来,于是答案就是\(A\times A\times 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\n",tax[x=read()]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/asuldb/p/12005678.html