題解 CF255D 【Mr. Bender and Square】
阿新 • • 發佈:2020-11-13
圖掛了,再交一遍。
翻譯
給出一個 \(n\times n\) 的正方形和一個點的座標(\(x,y\)),從這個點每秒可以向外擴散四個點,即 \((x+1,y),(x-1,y),(x,y+1),(x,y-1)\) ,求需要多少秒才能大於或等於面積 \(c\)
思路
如果將這個點看作是在無限大的正方形上擴散,那麼我們可以得出:
擴散時間: 0 1 2
點的數量: 1 5 13
於是,為了得出擴散時間和點的數量的關係,設一個二次函式為 \(y=ax^2+bx+c\) 。( \(x\) 為擴散時間, \(y\) 為點的數量)
將上表的資料帶入二次函式就得到了一個三元一次方程,圖片如下:
\(\therefore\) 這個二次函式為: \(y=2x^2+2x+1\)
現在我們開始考慮邊緣阻擋了的點的數量。
不難發現,在邊緣以外需要減去的點組成了一個像金字塔一樣的三角形(第一層有 \(1\) 個,第二層有 \(3\) 個 ……),圖片如下(手畫很醜,請見諒):
這個圖片的擴散時間為 \(3\) ,藍色區域代表點,紅色邊框在 \(3\times 3\) 的正方形邊緣外,綠色圓圈圈出的三角形即為突出部分。
提供一下小學奧數的知識:
\(1+3+5+...+2n-1=n^2\)
因此,就可以得出突出部分的點數,其他幾個邊也一樣。
然後,你會發現突出部分有重疊,如下圖綠圈部分:
多次畫圖後,發現:重疊部分是個每層點數相差1的三角形,於是就可以用高斯求和 \((1+2+3+...+n=\frac{(1+n)n}{2})\)
所以總的點數=忽略邊緣時的點數-四邊突出的點數+重疊部分的點數。
注:+重疊部分的點數是根據容斥原理
有了公式,就可以二分查詢答案了!
程式碼
注:二分查詢注意邊界!
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int INF=1e9+10; ll n,x,y,c; int main() { cin>>n>>x>>y>>c; x--;y--; ll l=0,r=2*n+1,ans=INF; while(l<=r) { ll mid=(l+r)/2; ll s=2*mid*mid+2*mid+1; //忽略邊界的點數 if(mid-x>0) s-=(mid-x)*(mid-x); //上邊突出部分 if(mid-(n-1-x)>0) s-=(mid-(n-1-x))*(mid-(n-1-x)); //下邊突出部分 if(mid-y>0) s-=(mid-y)*(mid-y); //左邊突出部分 if(mid-(n-1-y)>0) s-=(mid-(n-1-y))*(mid-(n-1-y)); //右邊突出部分 if(mid-x-(n-y-1)-1>0) s+=(1+mid-x-(n-y-1)-1)*(mid-x-(n-y-1)-1)/2; //右上重疊部分 if(mid-(n-1-x)-(n-1-y)>0) s+=(1+mid-(n-1-x)-(n-1-y)-1)*(mid-(n-1-x)-(n-1-y)-1)/2; //右下重疊部分 if(mid-(n-1-x)-y-1>0) s+=(1+mid-(n-1-x)-y-1)*(mid-(n-1-x)-y-1)/2; //左下重疊部分 if(mid-y-x-1>0) s+=(1+mid-y-x-1)*(mid-y-x-1)/2; //左上重疊部分 if(s>=c) { r=mid-1; ans=min(mid,ans); } else { l=mid+1; } } cout<<ans<<endl; return 0; }