1. 程式人生 > 其它 >2021.7.10 校內模擬賽遊記

2021.7.10 校內模擬賽遊記

嚴重事故徵候 over and over again

這次 事故徵候 模擬賽,暴露出我 安全意識淡薄,形式主義突出 省略標準程式的老問題。
T2 掛成 \(0\) 分了。

A

給定序列 \(a\), 問能否通過 \(a_i \to a_{i-1} + a_{i+1} - a_i\) 的操作變成 \(b\)

看到 A 題嚇死了,開始想了 30min+ 沒有思路,先跳過了。

然後寫完 T2, 看過 3、4 後又來想,恍然大悟了。
首先如果把三個數都減去 \(x\), 那麼最後結果減少了倆加上了一個,所以結果也被減去了 \(x\),並不會對數的相對大小造成什麼影響,那麼就簡化問題,吧 \(x, y, z\)

三個數變成 \(0, y-x, z-x\), 當作 \(0, x, y\) 來處理,進行一次操作後,發現數列變成了 \(0, y-x, y\), 驚喜地發現,差交換了位置!

眾所周知,排列兩兩交換能達到任何排列,而換不出其它數來,所以只要比較差的多重集是否相同就可以了。

B

這就是出事的題。

構造排列滿足輸入的相鄰兩數的大小關係,同時讓 LIS 儘可能 大/小

很快就想到了一個可行的構造,雖然有點複雜,但至少是對的,寫完調了一會兒就放著了。

所謂的檢查單完全只是掃了兩眼程式碼,測試部分也只檢查了是否是一個排列,而沒有檢查相對大小的關係,然後就成功掛分了。

可笑的是,程式碼的末尾還寫著

// 0137Z - CCP
// 0142Z - CKC

其實連檢查單都沒有默出來就打上了 CKC 的標記。

今後必須要嚴格執行檢查單,並且強制要求在程式碼末尾默寫檢查單且兩個標記不得使用縮寫,強制要求寫完全稱。

C

有箱子的網格圖裡從左上到右下,可以推箱子但不能推出去,求路徑數。

想到了 dp 要一塊轉移,可是恍然發現這樣會有重複。
然後就以為這是個錯誤的思路,直接棄掉,想了會兒容斥未果就寫了個暴力交了。

有重複就想辦法解決啊!!!
其實只要強制規定當前格轉向,然後一塊的轉移用字首和優化就可以了。

程式碼裡保留了原來的程式碼。

void TYT() {
	for (int i = 1; i <= n; i++) std::cin >> (map[i] + 1);
	for (int i = n; i >= 1; i--)
		for (int j = m; j >= 1; j--)
			r[i][j] = r[i][j+1] + (map[i][j] == 'R'),
			d[i][j] = d[i+1][j] + (map[i][j] == 'R');
	f[n][m][0] = f[n][m][1] = sum[n][m][0] = sum[n][m][1] = 1;
	for (int i = n; i >= 1; i--)
		for (int j = m; j >= 1; j--) {
			if (i == n && j == m) continue;
			f[i][j][0] = (sum[i][j+1][1] - sum[i][m-r[i][j+1]+1][1] + P) % P;
			f[i][j][1] = (sum[i+1][j][0] - sum[n-d[i+1][j]+1][j][0] + P) % P;
			sum[i][j][0] = (sum[i+1][j][0] + f[i][j][0]) % P;
			sum[i][j][1] = (sum[i][j+1][1] + f[i][j][1]) % P;
		}
	std::cout << (f[1][1][1] + f[1][1][0]) % P;
}

D

我居然沒有想到那麼顯然的鏈上部分分的倍增?!

想了半天未果,連暴力都沒有想出來。成功 \(0\) 分。

題解在這裡寫了,不重複發了。