Codeforces 135E - Weak Subsequence

Posted by ratcateme on Mon, 03 Jan 2022 19:55:37 +0100

MARK on 2022.1.3: because I think the blog "choose to do miscellaneous problems in combinatorial mathematics" is too cumbersome, I deleted it and wrote all the problem solutions in a separate blog.

Codeforces Title portal & Rogue portal

Good problems in combinatorial mathematics.

Key observation: for a string \ (s \), the length of the longest "weak substring" is equal to \ (|s \) minus \ (\ min(s\text {prefix} with different longest characters and suffix}) with different longest characters).

Proof: let's prove a lemma first: if a substring is a weak substring of \ (s \), its corresponding subsequence that meets the requirements must be obtained by moving a character on the basis of the substring. The proof of this theorem is probably to consider a subsequence \ (i_1, i_2, \ cdots, i_k (i_t < i_ {T + 1}) \) and a substring \ (j_1, j_2, \ cdots, j_k (j_t < j_ {T + 1}) \), if they share the number of elements \ (< k-1 \), then we consider that the largest \ (t \) satisfies \ (i_t < j_t \), because \ (t \) is the largest subscript in the required subscript, there must be \ (i_t + 1} \ Ge j_ {T + 1} \), Therefore, there are no selected elements between \ (j_t\sim i_{t+1} \), we can directly change \ (i_t \) to \ (j_t \), so that the size of the coincident part will be \ (+ 1 \), and because the size of the original coincident part \ (< k-1 \), after the modification, the sub sequence still meets the requirements of weak sub sequence, so our modification meets the requirements. This continues until the overlapping part reaches \ (k-1 \).

So we might as well consider a substring. Since we can only move one element, we can only move the first or last element. If we move the first element, we find the prefix length \ (len \) with different longest characters of \ (s \), and make the substring \ (s[len+1... |s|] \), It is easy to prove that this operation is the best in all cases where only the first element is moved. It is also similar to the case where the last element is moved. The two take \ (\ max \) as \ (| s|-\min(s\text {the longest characters have different prefixes}, and s\text {the longest characters have different suffixes}) \).

Next, consider how to calculate the answer. Considering tolerance and exclusion, the answer can be obtained by subtracting the number of schemes with weak substring length \ (\ le w \) from the number of schemes with weak substring length \ (\ le w-1 \), so the problem is transformed into finding the number of schemes with the longest weak substring length \ (\ le w \). According to the above formula, the length of the length \ (\ Le, w \) meets the requirements. The scheme number \ (\ sum \ limits {i = 1} ^ wk ^ i \) and the sum / divide and conquer of a wave equal ratio sequence are taken away. For the case of length \ (w+i(i\in[1,k]) \), the string meets the requirements if and only if the first \ (i \) bits are different from each other and the last \ (i \) bits are also different from each other. Continue to divide the case:

  • If \ (2i\le w+i \), the first \ (I \) bit and the last \ (I \) bit are independent, and the number of schemes \ ((k ^ {\ underline {I}) ^ 2 · k^{w-i} \).
  • Otherwise, remember \ (c=2i-(w+i) \), then the number of intermediate schemes \ (k^{\underline{c} \), the number of schemes on both sides is \ ((k-c)^{\underline{i-c} \), and the total number of schemes \ (k^{\underline{c} · ((k-c)^{\underline{i-c}})^2 \)

For strings with length \ (> W + k \), the character set size is \ (k \), which obviously does not meet the requirements.

It can be calculated directly. The time complexity is \ (k\log w \).

const int MAXN = 1e6;
const int MOD = 1e9 + 7;
int k, w, fac[MAXN + 5], ifac[MAXN + 5];
int qpow(int x, int e) {
	int ret = 1;
	for (; e; e >>= 1, x = 1ll * x * x % MOD)
		if (e & 1) ret = 1ll * ret * x % MOD;
	return ret;
}
void init_fac(int n) {
	for (int i = (fac[0] = ifac[0] = ifac[1] = 1) + 1; i <= n; i++)
		ifac[i] = 1ll * ifac[MOD % i] * (MOD - MOD / i) % MOD;
	for (int i = 1; i <= n; i++) {
		fac[i] = 1ll * fac[i - 1] * i % MOD;
		ifac[i] = 1ll * ifac[i - 1] * ifac[i] % MOD;
	}
}
int calc_spw(int t, int k) {
	if (!t) return 0; if (t == 1) return k;
	int mid = t >> 1, sum = calc_spw(mid, k);
	sum = (sum + 1ll * sum * qpow(k, mid)) % MOD;
	if (t & 1) sum = (sum + qpow(k, t)) % MOD;
	return sum;
}
int calc_A(int n, int k) {
	if (n < k) return 0;
	return 1ll * fac[n] * ifac[n - k] % MOD;
}
int calc(int k, int w) {
	int ss = calc_spw(w, k);
	for (int i = 1; i <= k; i++) {
		int len = i + w;
		if (i + i <= len) ss = (ss + 1ll * calc_A(k, i) * calc_A(k, i) % MOD * qpow(k, len - i - i)) % MOD;
		else {
			int cap = i + i - len;
			ss = (ss + 1ll * calc_A(k, cap) * calc_A(k - cap, i - cap) % MOD * calc_A(k - cap, i - cap)) % MOD;
		}
	}
//	printf("%d %d %d\n", k, w, ss);
	return ss;
}
int main() {
	scanf("%d%d", &k, &w); init_fac(MAXN);
	printf("%d\n", (calc(k, w) - calc(k, w - 1) + MOD) % MOD);
	return 0;
}