1. 程式人生 > 實用技巧 >[BZOJ2969] 矩形粉刷

[BZOJ2969] 矩形粉刷

[BZOJ2969] 矩形粉刷

為了慶祝新的一年到來,小M決定要粉刷一個大木板。大木板實際上是一個\(W×H\)的方陣。小M得到了一個神奇的工具,這個工具只需要指定方陣中兩個格子,就可以把這兩格子為對角的,平行於木板邊界的一個子矩形全部刷好。小M樂壞了,於是開始胡亂地使用這個工具。
 假設小M每次選的兩個格子都是完全隨機的(方陣中每個格子被選中的概率是相等的),而且小M使用了\(K\)次工具,求木板上被小M粉刷過的格子個數的期望值是多少。

Input

第一行是整數\(K,W,H\)

Output

一行,為答案,四捨五入保留到整數。

Example

輸入 #1

\(1\) \(3\) \(3\)

輸出 #1

\(4\)

Explanation

標準答案約為3.57

Scoring

\(100%\)的資料滿足:\(1≤W,H≤1000,1≤K≤100\)

比賽時候突然開光想出來了orz,有丶像去年J組第三題

對於每個格子,考慮一個隨機的矩形不能塗到它的概率有多少

顯然,對於一個點\((i,j)\),如果選出的兩個點都在它的上面/下面/左邊/右邊肯定是覆蓋不到它的

把兩個點都在上下左右的概率加起來,再減去都在左上角/右上角/左下角/右上角的概率(這些算了兩遍),就是執行一遍操作時,\((i,j)\)覆蓋不到的概率,設這個數為\(p\)

最後答案就把每個點的\((1-p^k)\)加起來就好了

毫無可讀性的程式碼:

//:D 
#include<bits/stdc++.h> 
using namespace std;

int k, w, h;
double pic[1005][1005];

double Pow(double a, int x) {
	double s = 1.0;
	while (x--) s *= a;
	return s;
}

int main() {
	scanf("%d %d %d", &k, &w, &h);
	for (int i = 1; i <= w; i++) {//行 
		for (int j = 1; j <= h; j++) {//列 
			double qwq=
			 Pow(1.0 * (i - 1) / w, 2) + Pow(1.0 * (w - i) / w, 2)//全在上面+全在下面
			+Pow(1.0 * (j - 1) / h, 2) + Pow(1.0 * (h - j) / h, 2)//全在左邊+全在右邊 
			-Pow(1.0 * (i - 1) / w, 2) * Pow(1.0 * (j - 1) / h, 2)//-全在左上
			-Pow(1.0 * (i - 1) / w, 2) * Pow(1.0 * (h - j) / h, 2)//-全在左下
			-Pow(1.0 * (w - i) / w, 2) * Pow(1.0 * (j - 1) / h, 2)//-全在右上
			-Pow(1.0 * (w - i) / w, 2) * Pow(1.0 * (h - j) / h, 2);//-全在右下 
			//cout<<qwq<<" ";
			pic[i][j] = qwq;
		}
		//cout<<endl;
	}
	double cnt = 0.0;
	for (int i = 1; i <= w; i++) {
		for (int j = 1; j <= h; j++) {
			cnt += (1 - Pow(pic[i][j], k));
			//cout<<cnt<<endl;
		}
	}
	cout<<(int)(cnt + 0.5);
	return 0;
}

但我還是想看歡天喜地