Official

F - typewriter Editorial by en_translator


This problem can be solved with inclusion-exclusion principle.

For example, when \(N=3\), we have

\((\) The number of strings that can be typed using at least one of \(1\)-st row, \(2\)-nd row, or \(3\)-rd row\() = \)
\(+\) (strings that can be typed using \(1\)-st row)
\(+\) (strings that can be typed using \(2\)-nd row)
\(+\) (strings that can be typed using \(3\)-rd row)
\(-\) (strings that can be typed using either \(1\)-st row or \(2\)-nd row) \(-\) (strings that can be typed using either \(1\)-st row or \(3\)-rd row) \(-\) (strings that can be typed using either \(2\)-nd row or \(3\)-rd row) \(+\) (strings that can be typed using any of \(1\)-st row, \(2\)-nd row, or \(3\)-rd row).

(For small \(N\), drawing a Venn diagram may help you understanding.)

Since \(N\) is as small as \(N \le 18\), we consider iterating all of the \(2^N-1\) sets of rows. If we can solve the following problem, then the original problem can be solved.

How many strings can be typed with all of the \(A_1\)-th, \(A_2\)-th, \(\ldots A_k\)-th rows? (For the rows not included in \(A\), the string may not be typed with that row.)

We seek for the necessary and sufficient condition that a string \(S\) satisfies the condition.
Obviously, every character in \(S\) has to be typed with every row included in \(A\). Conversely, if \(S\) consists only of characters that can be typed with all rows in \(A\), then \(S\) satisfies the condition.
Therefore, the answer for the problem is (the number of distinct alphabets that can be typed with all rows in \(S\))\(^l\).

By computing this count for all of the \(2^N-1\) and adding and subtracting properly according to Inclusion-Exclusion principle, you can obtain the correct answer for this problem. The time complexity is \(O(2^NN)\).
In the sample code, “the number of distinct alphabets that can be typed with all rows in \(S\)” is counted fast using bit operations.

Sample code (C++)

#include<bits/stdc++.h>
#define mod 998244353

using namespace std;

long long power(long long a,long long b){
  long long x=1,y=a;
  while(b>0){
    if(b&1ll){
      x=(x*y)%mod;
    }
    y=(y*y)%mod;
    b>>=1;
  }
  return x%mod;
}

int main(){
  int n,k;
  cin >> n >> k;
  vector<int> v(n,0);
  for(int i=0;i<n;i++){
    string s;
    cin >> s;
    for(auto &nx : s){v[i]|=(1<<(nx-'a'));}
  }

  long long res=0;
  for(int i=1;i<(1<<n);i++){
    int ch=(1<<26)-1;
    for(int j=0;j<n;j++){
      if(i&(1<<j)){ch&=v[j];}
    }
    int pc=__builtin_popcount((unsigned int)ch);
    if(__builtin_popcount((unsigned int)i)%2){res+=power(pc,k);res%=mod;}
    else{res+=(mod-power(pc,k));res%=mod;}
  }

  cout << res << '\n';
  return 0;
}

posted:
last update: