/* Check cf5-opt.vim defs. VIM: let g:lcppflags="-std=c++11 -O2 -pthread" VIM: let g:wcppflags="/O2 /EHsc /DWIN32" VIM: let g:cppflags=g:Iboost.g:Itbb VIM: let g:ldflags=g:Lboost.g:Ltbb.g:tbbmalloc.g:tbbmproxy VIM: let g:ldlibpath=g:Bboost.g:Btbb VIM: let g:argv="" */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef long long ll; typedef std::vector vec; void check( bool b ) { if ( !b ) std::cerr << "error" << std::endl; } #define FOR(i,l) for ( ll i =0, ie = ll(l); i void readv( V& v, int n ) { v.reserve(n); for ( int i = 0; i < n; ++i ) { typename V::value_type e; std::cin >> e; check( !std::cin.fail() ); v.push_back(e); } } template ll perm( V& v, size_t idx = 0 ) { std::vector p(26,0); char c = 0; for ( int j = 0; j < idx+1; ++j ) { for( auto l : v[j] ) { if ( c != l ) { if ( p[ l-'a' ] ) return 0; else p[ l-'a' ] = 1; c = l; } } } if ( idx == v.size()-1 ) return 1; ll r = 0; for( size_t i = idx; i < v.size(); i++ ) { std::swap(v[idx],v[i]); r += perm(v,idx+1); std::swap(v[idx],v[i]); } return r; } template bool remove_group( V& s, int a, S& rc ) { int c = a; for ( auto jt = s.begin(); jt != s.end(); ) { if ( (*jt)[0] == c ) { for( auto l : *jt ) { if ( c != l ) { if ( rc.find(l) != rc.end() ) return false; else { rc.insert(l); c = l; } } } jt = s.erase(jt); } else ++jt; } c = a; for ( auto jt = s.begin(); jt != s.end(); ) { if ( (*jt).back() == c ) { for( auto i = jt->size()-1; i >= 0; --i ) { int l = (*jt)[i]; if ( c != l ) { if ( rc.find(l) != rc.end() ) return false; else { rc.insert(l); c = l; } } } jt = s.erase(jt); } else ++jt; } return true; } ll solve_puzzle() { int n; std::cin >> n; const ll m = 1000000007; std::vector s; readv(s,n); std::vector p(26,0); for ( auto it = s.begin(); it != s.end(); ) { bool b = true; char c = (*it)[0]; for( auto l : *it ) { if ( c != l ) { b = false; break; } } if ( b ) { p[c-'a']++; it = s.erase(it); } else ++it; } ll coef = 1; for ( int i = 0; i < p.size(); ++i ) { auto r = p[i]; while( r > 1 ) coef *= r--; } std::set rc; int g = 0; for ( int i = 0; i < p.size(); ++i ) { if ( p[i] > 0 && rc.find(i+'a') == rc.end() ) { g++; if ( !remove_group( s, i+'a', rc ) ) return 0; } } while ( s.size() ) { g++; if ( !remove_group( s, s.front().front(), rc ) ) return 0; } ll i = 1; while ( g > 1 ) i *= g--; return (i*coef)%m; } int main ( void ) {try{ srand((unsigned)time(NULL)); int puzzle_count; std::cin >> puzzle_count; std::cin.ignore(std::numeric_limits::max(),'\n'); for ( int i = 1; i <= puzzle_count; i++ ) { std::cout << "Case #" << i << ": "; auto r = solve_puzzle(); std::cout << r << std::endl; } return 0; } catch ( const std::exception& e ) { std::cerr << std::endl << "std::exception(\"" << e.what() << "\")." << std::endl; return 2; } catch ( ... ) { std::cerr << std::endl << "unknown exception." << std::endl; return 1; }}