个点的图。记一个匹配的权值为 ,求所有匹配的权值和。
。
个点的图,每条边 种。对于 ,求大小为 的匹配的数量。
。
直接状压 。
在一个合法匹配的基础上加上边 ,新图每个点 ,一定是若干个链/环。并且新图只有 个连通块,可以 状压将 这些连通块合在一起的权值。
然后枚举子集 或集合幂级数 exp 。
int n,m,c;
int e[maxn<<1],msk[1<<maxn];
int f[1<<maxn][maxn<<1],g[1<<maxn],dp[1<<maxn];
void work(){
n=read();m=read();c=read();
if(n&1)n++;
for(int i=1;i<=m;i++){
int u=read()-1,v=read()-1;
e[u]|=1ll<<v,e[v]|=1ll<<u;
}
for(int s=0;s<(1<<n/2);s++){
for(int i=0;i<n/2;i++)if(!(s&(1<<i)))msk[s]|=(1ll<<2*i)|(1ll<<2*i+1);
}
for(int i=0;i<n;i++)f[1<<i/2][i]=1;
for(int s=0;s<(1<<n/2);s++){
for(int i=0;i<n;i++)if(f[s][i]){
for(int t=e[i]&msk[s];t;t&=t-1){
int j=__builtin_ctzll(t);
(f[s^(1<<j/2)][j^1]+=f[s][i]*c)%=mod;
}
g[s]+=f[s][i];
}
}
for(int s=0;s<(1<<n/2);s++)g[s]=g[s]%mod*(mod+1)/2%mod;
for(int mx=2;mx<=n;mx+=2){
for(int s=(1<<mx/2-1);s<(1<<mx/2);s++)mems(f[s],0);
f[1<<mx/2-1][mx-2]=1;
for(int s=(1<<mx/2-1);s<(1<<mx/2);s++){
for(int i=0;i<mx;i++)if(f[s][i]){
for(int t=e[i]&msk[s]&((1ll<<mx)-1);t;t&=t-1){
int j=__builtin_ctzll(t);
(f[s^(1<<j/2)][j^1]+=f[s][i]*c)%=mod;
}
if(e[i]&(1ll<<mx-1))(g[s]+=f[s][i]*c)%=mod;
}
}
}
ni[0]=ni[1]=1;for(int i=2;i<=n/2;i++)ni[i]=(mod-mod/i)*ni[mod%i]%mod;
xorexp(g,dp,n/2);
printf("%lld\n",dp[(1<<n/2)-1]);
}