WC之前写的,补一补,但是基本就是学新知识了
首先可以枚举子集$3^n$转移,优化是额外记录每个集合选取的个数,然后按照选取个数从小到大转移。转移的时候先FWT成“点值”转移完了IFWT回去乘逆元
沙茶博主也不知道为什么这样就是对的,放个没看懂的yww大佬的博客
1 // luogu-judger-enable-o2 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=22,M=(1<<N)+N,K=110,mod=998244353; 7 int mat[N][N],val[N],aset[N],deg[N],inv[N*K]; 8 int sum[M],gain[N][M],dp[N][M],bit[M]; 9 int n,m,p,t1,t2,all,lth; 10 void Mod(int &x,int y) 11 { 12 x+=y; 13 if(x<0) x+=mod; 14 if(x>=mod) x-=mod; 15 } 16 int S(int x) 17 { 18 return 1<<(x-1); 19 } 20 int Val(int x) 21 { 22 return p?(p==1?x:1ll*x*x%mod):1; 23 } 24 int Finda(int x) 25 { 26 return aset[x]==x?x:aset[x]=Finda(aset[x]); 27 } 28 int Calc(int sta) 29 { 30 register int i,j; 31 int abe=0,nde=0; 32 for(i=1;i<=n;deg[i]=0,i++) 33 if(sta&S(i)) aset[i]=i; 34 for(i=1;i<=n;i++) 35 if(sta&S(i)) 36 { 37 nde=i,sum[sta]+=val[i]; 38 for(j=1;j<=n;j++) 39 if((sta&S(j))&&mat[i][j]) 40 deg[i]++,aset[Finda(j)]=Finda(i); 41 if(deg[i]%2) abe=1; 42 } 43 int anc=Finda(nde); 44 for(i=1;i<=n;i++) 45 if(sta&S(i)) abe|=Finda(i)!=anc; 46 return abe*Val(sum[sta]); 47 } 48 void Trans(int *arr,int len,int typ) 49 { 50 register int i,j,k; 51 for(i=2;i<=len;i<<=1) 52 { 53 int lth=i>>1; 54 for(j=0;j<len;j+=i) 55 for(k=j;k<j+lth;k++) 56 Mod(arr[k+lth],typ*arr[k]); 57 } 58 } 59 void Pre() 60 { 61 register int i; 62 scanf("%d%d%d",&n,&m,&p),lth=1<<n,all=lth-1; 63 for(i=1;i<=m;i++) 64 { 65 scanf("%d%d",&t1,&t2); 66 mat[t1][t2]=mat[t2][t1]=true; 67 } 68 for(i=1;i<=n;i++) scanf("%d",&val[i]); 69 dp[0][0]=1,inv[1]=1,Trans(dp[0],lth,1); 70 for(i=2;i<=2100;i++) 71 inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod; 72 for(i=0;i<=all;i++) 73 bit[i]=bit[i>>1]+(i&1),gain[bit[i]][i]=Calc(i); 74 for(i=0;i<=n;i++) Trans(gain[i],lth,1); 75 } 76 int main() 77 { 78 Pre(); 79 register int i,j,k; 80 for(i=1;i<=n;i++) 81 { 82 for(j=0;j<=i;j++) 83 for(k=0;k<=all;k++) 84 Mod(dp[i][k],1ll*dp[j][k]*gain[i-j][k]%mod); 85 Trans(dp[i],lth,-1); 86 for(int j=0;j<=all;j++) 87 dp[i][j]=(bit[j]==i)?1ll*dp[i][j]*Val(inv[sum[j]])%mod:0; 88 if(i!=n) Trans(dp[i],lth,1); 89 } 90 printf("%d",dp[n][all]); 91 return 0; 92 }