2020 CCPC Wannafly Winter Camp Day1 Div.1&2(A題 期望逆序對)(找規律)

2020 CCPC Wannafly Winter Camp Day1 Div.1&2(A題 期望逆序對)(找規律)

時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 262144K,其他語言524288K
64bit IO Format: %lld

題目描述

nn 個獨立的隨機變量,其中 xix_i 的值是一個從 [li,ri][l​_i ,r_i] 中隨機選取的整數,即對於 [li,ri][l​_i ,r_i] 中的任何一個整數 jjxi=jx_i= j 的概率都是 (rili+1)1(r_i-l_i+1)^{-1} 現在你需要給出一個長度爲 n{n} 的排列 p{p},那麼可以得到一個長度爲 n{n} 的隨機變量序列 。你的目標是讓結果序列的逆序對個數的期望儘可能少。
求逆序對個數的期望的最小值。

輸入描述:

第一行輸入一個整數 n(1n5×103){n}(1\leq n \leq 5\times 10^3) 接下來 nn 行每行兩個整數 li,ri(1liri109)l_i,r_i (1\leq l_i \leq r_i\leq 10^9)

輸出描述:

輸出一行一個整數,表示答案對 998244353998244353 取模後的值。假設答案的最簡分數表示是 xy\frac{x}{y} ,你需要輸出一個整數 kk 滿足 k×yxmod998244353k \times y \equiv x \bmod 998244353

示例1

輸入

3
1 2
2 3
1 3

輸出

332748118

題解

官方題解爲:
在這裏插入圖片描述
但我回來反覆琢磨後發現一處問題:

在這裏插入圖片描述
這個式子在 r1>l2r_1 > l_2 的時候處理的不太對,不過題解代碼倒是沒什麼問題。

假如有區間 11[1,3][1,3] 區間 22[2,4][2,4] ,那麼枚舉區間 11 的元素時,當 ii22 的時候 此時若想讓區間 11 的元素大於區間 22 的元素,那麼無論區間 22 取哪個,都是不可能的,而官方題解的式子裏可以看出區間 22 裏有 11 中取法(max(0,min(2,4)2+1)max(0,min(2,4)-2+1)11 ),這顯然是不符合的;當 ii33 的時候,此時區間 22 裏只有一種取法,就是取 22 ,但是官方題解的式子裏得出了 22 種取法(max(0,min(3,4)2+1)max(0,min(3,4)-2+1)22 ),這顯然也是不符合的。

也就是說當 r1>l2r_1 > l_2 的時候,每次枚舉都會多加 11

修改後的式子:
(r1l1+1)1(r2l2+1)1i=l1r1max(0,min(i,r2+1)l2)(r_1-l_1+1)^{-1}(r_2-l_2+1)^{-1}\sum_{i=l_1}^{r_1}{max(0,min(i,r_2+1)-l_2)}

ii 是否大於 r2r_2 進行分類討論:

rr 等於 min(r1,r2)min(r_1,r_2) ,把區間 11r2r_2 爲邊界拆成 [l1,r][l_1,r],和 (r,r1](r,r_1] 兩部分(如果 rr 等於 r1r_1 ,那麼第二部分爲空集),計算第一部分對應的取值情況種類應該有 (ll2+rl2)(rl+1)/2(l-l_2+r-l_2)(r-l+1)/2(等差數列求和,見於代碼第33行),計算第二部分對應的取值情況種類應該有 (r1r)(r2l2+1)(r_1-r)(r_2-l_2+1)見於代碼第34行)。

代碼

#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
struct atom {
	int l, r;
	void scan() {
		scanf("%d%d", &l, &r);
	}
};
const int N = 5100;
const int mo = 998244353;
int operator < (atom k1, atom k2) {
	return k1.l + k1.r < k2.l + k2.r;
}
int n, inv[N];
atom A[N];
int quick(int k1, int k2) {
	int k3 = 1;
	while (k2) {
		if (k2 & 1) k3 = 1ll * k3*k1%mo;
		k2 >>= 1; k1 = 1ll * k1*k1%mo;
	}
	return k3;
}
int calc(atom k1, atom k2) {
	int l = max(k1.l, k2.l);
	if (l > k1.r) return 0;
	int r = min(k1.r, k2.r);
	int ans = 1ll * (l - k2.l + r - k2.l)*(r - l + 1) / 2 % mo;
	ans = (ans + 1ll * (k1.r - r)*(k2.r - k2.l + 1)) % mo;
	return ans;
}
int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) A[i].scan();
	sort(A + 1, A + n + 1);
	int ans = 0;
	for (int i = 1; i <= n; i++) inv[i] = quick(A[i].r - A[i].l + 1, mo - 2);
	for (int i = 1; i <= n; i++)
		for (int j = i + 1; j <= n; j++)
			ans = (ans + 1ll * inv[i] * inv[j] % mo*calc(A[i], A[j])) % mo;
	cout << ans << endl;
	return 0;
}
發佈了179 篇原創文章 · 獲贊 56 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章