/* 统计方案的时候,我们只考虑字符串的内容。不同来源生成的同样的字符串只算一种方案。所以重点思考字符的来源。 以n=3n=3为例,可以打印出的长度为L的字符串总数=(使用第1行的字符集打印出的字符串总数+使用第2行的字符集打印出的字符串总数+使用第3行的字符集打印出的字符串总数)-(使用第1行或第2行的字符集打印出的字符串总数+使用第2行或第3行的字符集打印出的字符串总数+使用第1行或第3行的字符集打印出的字符串总数)+(使用第1行或第2行或第3行的字符集打印出的字符串总数)=(使用第1行的字符集打印出的字符串总数+使用第2行的字符集打印出的字符串总数+使用第3行的字符集打印出的字符串总数)?(使用第1行或第2行的字符集打印出的字符串总数+使用第2行或第3行的字符集打印出的字符串总数+使用第1行或第3行的字符集打印出的字符串总数)+(使用第1行或第2行或第3行的字符集打印出的字符串总数)。 由于nn不超过1818,可以用00到2^{18}-12 18 ?1表示每一行取或不取的可能性。从00到2^{18}-12 18 ?1枚举i,如果ii包含奇数个11,说明该组合在容斥原理中要“加上”;如果ii包含偶数个11,说明该组合在容斥原理中要“减去”。 设i包含kk个11,我们还要快速求出这kk个字符集的交集。因为字符集最多2626个字母,而int有3232位,因此用3232位整数作为位示图,其中低2626位对应2626个字母出现或不出现即可。*/ #include using namespace std; typedef long long ll; typedef pair pii; const int maxn = 18; const int mod = 998244353; int n, L, mask[18]; char s[18][27]; ll ans; ll qpow(ll a, ll b) { ll re = 1; while (b != 0) { if ((b & 1) == 1) re = re * a % mod; a = a * a % mod; b >>= 1; } return re; } int Count(int x) { int cnt = 0; while (x != 0) { if ((x & 1) == 1) cnt++; x >>= 1; } return cnt; } int main() { scanf("%d%d", &n, &L); for (int i = 0; i < n; i++) { scanf("%s", s[i]); for (int j = 0; s[i][j] != '\0'; j++) mask[i] |= (1 << (s[i][j] - 'a')); } for (int i = 1; i < (1 << n); i++) { int ch = (1 << 26) - 1, cnt = 0; for (int j = 0; j < n; j++) if (((1 << j)&i) != 0) cnt++, ch &= mask[j]; if ((cnt & 1) == 1) ans = (ans + qpow(Count(ch), L)) % mod; else ans = (ans + (mod - qpow(Count(ch), L)) % mod) % mod; } printf("%lld\n", ans); return 0; }