Codeforces 775 E Tyler and Strings

Posted by dabigchz on Tue, 08 Mar 2022 09:13:11 +0100

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;
}