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 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
| #include "iostream" #include "algorithm" #include "cstring" #include "cstdio" #include "cmath" #include "vector" #include "map" #include "set" #include "queue" using namespace std; #define MAXN 18
#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 ) typedef long long ll; int n , q;
void IFWTand( ll* A , int len ) { for( int mid = 1 ; mid < len ; mid <<= 1 ) for( int i = 0 ; i < len ; i += ( mid << 1 ) ) for( int j = 0 ; j < mid ; ++ j ) ( A[i + j] -= A[i + j + mid] ); }
void FWTor( ll* A , int len ) { for( int mid = 1 ; mid < len ; mid <<= 1 ) for( int i = 0 ; i < len ; i += ( mid << 1 ) ) for( int j = 0 ; j < mid ; ++ j ) A[i + j + mid] += A[i + j]; }
void IFWTor( ll* A , int len ) { for( int mid = 1 ; mid < len ; mid <<= 1 ) for( int i = 0 ; i < len ; i += ( mid << 1 ) ) for( int j = 0 ; j < mid ; ++ j ) A[i + j + mid] -= A[i + j]; }
int G[MAXN][MAXN] , A[MAXN]; char ch[MAXN]; ll dp[MAXN][( 1 << 17 ) + 6]; ll pd[MAXN][( 1 << 17 ) + 6]; ll S[( 1 << 17 ) + 6]; int bc[MAXN] , cnt; ll F[300][( 1 << 17 ) + 6];
int getit( vi& a ) { int cur = n , ret = 0; for( int i = a.size() - 1 ; i >= 0 ; -- i ) { while( cur > a[i] ) -- cur , ret <<= 1; ret = ret << 1 | 1; } while( cur > 0 ) -- cur , ret <<= 1; return ret; }
vi dv; void dfs( int x , int pre ) { if( !x ) { int idx = getit( dv ); bc[idx] = ++ cnt; rep( i , 0 , ( 1 << n ) - 1 ) F[cnt][i] = 1; for( int l : dv ) rep( i , 0 , ( 1 << n ) - 1 ) F[cnt][i] = F[cnt][i] * pd[l][i]; IFWTor( F[cnt] , ( 1 << n ) ); return; } if( x < pre ) return; for( int i = pre ; i <= x ; ++ i ) dv.pb( i ) , dfs( x - i , i ) , dv.pop_back( ); }
ll s[( 1 << 16 ) + 6];
void solve() { cin >> n; rep( i , 1 , n ) { scanf("%s",ch + 1); rep( j , 1 , n ) G[i][j] = ch[j] - '0'; } rep( i , 1 , n ) dp[i][1 << i - 1] = 1; rep( sta , 1 , ( 1 << n ) - 2 ) rep( i , 1 , n ) if( ( sta & ( 1 << i - 1 ) ) && dp[i][sta] ) rep( j , 1 , n ) if( ( ~sta & ( 1 << j - 1 ) ) && G[i][j] ) dp[j][sta | ( 1 << j - 1 )] += dp[i][sta]; rep( i , 0 , ( 1 << n ) - 1 ) rep( j , 1 , n ) pd[__builtin_popcount( i )][i] += dp[j][i]; rep( i , 1 , n ) FWTor( pd[i] , ( 1 << n ) ); dfs( n , 1 ); rep( sta , 0 , ( 1 << n - 1 ) - 1 ) { dv.clear() , dv.pb( 1 ); rep( i , 1 , n - 1 ) { if( sta & ( 1 << i - 1 ) ) ++ dv.back(); else dv.pb( 1 ); } sort( all( dv ) ); int idx = getit( dv ); s[sta] = F[bc[idx]][( 1 << n ) - 1]; } IFWTand( s , ( 1 << n - 1 ) ); cin >> q; int re; rep( i , 1 , q ) { re = 0; scanf("%s",ch + 1); rep( j , 1 , n - 1 ) re |= ( ch[n - j] - '0' << j - 1 ); printf("%lld\n",s[re]); } }
signed main() {
solve(); }
|