Codeforces 775 E Tyler and Strings
meaning of the title
Give the string \ (s \) with length \ (n \) and the string \ (t \) with length \ (m \). If the characters in \ (s \) are rearranged, the string \ (p \) is generated, and the number of string \ (p \) is calculated to meet the dictionary order \ (p < T \). Output the value after taking the module of the answer pair \ (998244353 \).
The data satisfies: \ (1 \leq n,m,s_i,t_i \leq 2\times 10^5 \).
Problem solution
There are three situations for the length relationship between two strings: \ (| s | < | t 124\), \ (| s | = | t 124\) or \ (| s | > | t 124\).
Let's first consider the case where two strings are of equal length. If you want \ (p < T \), the string \ (p \) must meet:
- There is a position \ (i(1 \leq i \leq n) \) that satisfies \ (p_j = t_j (1 \ Leq J < I) \) and \ (p_i < t_i \).
For different strings \ (p \), we can enumerate the corresponding character position \ (i \) of the first string less than \ (t \), and the construction of \ (p \) is:
- \(p_j = t_j (1 \ Leq J < I) \), \ (p_i \) select any character less than \ (t_i \), and \ (p_j (I < J \ Leq n) \) can be selected at will.
We need to maintain the number of suffixes randomly arranged to form different strings, which is obviously a combinatorial number problem:
\(x_1 + x_2 + x_3 +... + x_k = tot \), find the number that can form different permutations.
The answer is: \ (\ frac{tot!}{x_1! ...x_p! ... x_k!}\).
If there is a number \ (W < t_i \) and there are still \ (x_p \) remaining, then if the number is placed at the \ (I \) position of \ (s \), the non repeated string that can be formed later is: \ (\ frac{(tot-1)!}{x_1! ...(x_p-1)! ... x_k!}\), This number should be added to the answer.
Notice \ (\ frac{(tot-1)!}{x_1! ...(x_p-1)! ... x_k!} = \frac{tot!}{x_1! ...x_p! ... x_k!} \times \frac{x_p}{tot} \), then if there are many different \ (W < t_i \), we can calculate them together.
Namely: \ (\ frac{tot!}{x_1! ...x_p! ... x_k!} \times \frac{x_{p1} + x_{p2} + ... x_{pr}}{tot}\)
Therefore, a data structure is needed to support single point modification and interval query, which can be easily realized with tree array.
According to the above method, the two situations of \ (| s | > | t 124\) and \ (| s | < | t 124\) are analyzed. It is found that one detail is not considered and improved:
- When \ (| s | < | t 124\), if the prefixes of \ (s \) and \ (t \) are exactly the same, it will be considered less once because there is no position \ (i(1 \leq i \leq n) \) to make \ (p_i < t_i \), but in fact, the dictionary order \ (P < T \) holds.
After special judgment, the problem can be passed smoothly, with time complexity \ (O(n \log_2 n) \).
C + + code example
# include <bits/stdc++.h> # define int long long # define lowbit(x) (x&(-x)) using namespace std; const int N = 2e5+10; const int mo = 998244353; int fac[N],c[N],a[N],b[N]; void update(int x,int d) { for (;x<=N-10;x+=lowbit(x)) c[x]+=d; } int query(int x) { int res=0; for (;x;x-=lowbit(x)) res+=c[x]; return res; } int pow(int x,int n) { int ans = 1; while (n) { if (n&1) ans = ans * x %mo; x=x*x%mo; n>>=1; } return ans; } int inv(int x) { return pow(x,mo-2); } signed main() { int n,m; cin>>n>>m; map<int,int>tmp; for (int i=1;i<=n;i++) { cin>>a[i]; update(a[i],1); tmp[a[i]]++; } for (int i=1;i<=m;i++) cin>>b[i]; fac[0]=1; for (int i=1;i<=N-10;i++) fac[i]=fac[i-1]*i%mo; int res = fac[n]; for (auto x :tmp) { res = res * inv(fac[x.second]) % mo; } int ans = 0,tot = n; for (int i=1;i<=min(n,m);i++) { (ans+=res*inv(tot)%mo*query(b[i]-1)%mo)%=mo; res=res*inv(tot)%mo*(query(b[i])-query(b[i]-1))%mo; tot--; update(b[i],-1); } if (n < m) { sort(a+1,a+1+n); sort(b+1,b+1+n); bool f = true; for (int i=1;i<=n;i++) if (a[i]!=b[i]) { f = false; break; } if (f) ans = (ans+1)%mo; } cout<<ans<<endl; return 0; }