1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| #include "iostream" #include "algorithm" #include "cstring" #include "cstdio" #include "cmath" #include "vector" #include "map" #include "set" #include "queue" using namespace std; #define MAXN ( 1 << 21 ) + 6
#define rep(i, a, b) for (int i = (a), i##end = (b); i <= i##end; ++i) #define per(i, a, b) for (int i = (a), i##end = (b); i >= i##end; --i) #define pii pair<int,int> #define fi first #define se second #define mp make_pair #define pb push_back #define eb emplace_back #define vi vector<int> #define all(x) (x).begin() , (x).end() #define mem( a ) memset( a , 0 , sizeof a ) #define min( a , b ) ( (a) < (b) ? (a) : (b) ) #define max( a , b ) ( (a) > (b) ? (a) : (b) ) #define P 998244353 typedef long long ll; int n , m , p;
int Pow( int x , int a ) { int cur = x % P , ans = 1; while( a ) { if( a & 1 ) ans = 1ll * ans * cur % P; cur = 1ll * cur * cur % P , a >>= 1; } return ans; }
int dp[22][MAXN] , f[MAXN] , F[22][MAXN] , w[MAXN]; int G[23][23];
int fa[23] , deg[23]; int find( int x ) { return x == fa[x] ? x : fa[x] = find( fa[x] ); } int chk( int s ) { rep( i , 1 , n ) fa[i] = i , deg[i] = 0; rep( i , 1 , n ) if( s & ( 1 << i - 1 ) ) rep( j , i + 1 , n ) if( ( s & ( 1 << j - 1 ) ) && G[i][j] ) { ++ deg[i] , ++ deg[j] , fa[find( j )] = find( i ); } int t = __builtin_ctz( s ) + 1; rep( i , 1 , n ) if( s & ( 1 << i - 1 ) ) { if( ( deg[i] & 1 ) || find( i ) != find( t ) ) return 1; } return 0; }
void FWTor( int* A , int len ) { for( int mid = 2 ; mid <= len ; mid <<= 1 ) for( int i = 0 ; i < len ; i += mid ) for( int j = i ; j < i + ( mid >> 1 ) ; ++ j ) ( A[j + ( mid >> 1 )] += A[j] ) %= P; } void IFWTor( int* A , int len ) { for( int mid = 2 ; mid <= len ; mid <<= 1 ) for( int i = 0 ; i < len ; i += mid ) for( int j = i ; j < i + ( mid >> 1 ) ; ++ j ) ( A[j + ( mid >> 1 )] += P - A[j] ) %= P; }
int calc( int x ) { return !p ? 1 : ( p == 1 ? x : 1ll * x * x % P ); }
int inv[MAXN];
void solve() { cin >> n >> m >> p; int u , v; rep( i , 1 , m ) { scanf("%d%d",&u,&v); G[u][v] = G[v][u] = 1; } rep( i , 1 , n ) scanf("%d",w + i); rep( i , 1 , ( 1 << n ) - 1 ) { f[i] = (f[i ^ (i & -i)] + w[__builtin_ctz(i & -i) + 1]), F[__builtin_popcount(i)][i] = chk(i) * calc(f[i]); inv[i] = Pow( calc( f[i] ) , P - 2 ); } int len = ( 1 << n ); rep( i , 0 , n ) FWTor( F[i] , ( 1 << n ) ); dp[0][0] = 1; FWTor( dp[0] , len ); rep( i , 1 , n ) { rep( j , 0 , i - 1 ) { rep( k , 0 , len - 1 ) ( dp[i][k] += 1ll * dp[j][k] * F[i - j][k] % P ) %= P; } IFWTor( dp[i] , len ); rep( k , 0 , len - 1 ) dp[i][k] = 1ll * dp[i][k] * inv[k] % P; if( i != n ) FWTor( dp[i] , len ); } printf("%d\n",dp[n][( 1 << n ) - 1]); }
signed main() {
solve(); }
|