Codeforces Edu 87 題解
標簽: 題解
Codeforces Edu 87
C. Simple Polygon Embedding【三分+計算幾何】
題目
對于一個邊長為1的正邊形,求其最小覆蓋正方形的邊長
題解
如果為偶數,那么該正多邊形可以旋轉成如下形式
其中四條邊與正方形邊界平行,因此正方形的邊長計算公式為
而如果為奇數,不論怎么旋轉最多只有兩條邊與正方形邊界平行
因此,可以用三分的方法在旋轉過程中找到一個最小覆蓋正方形。根據對稱性,旋轉角度只需要在。實際上,由對稱性不難猜出,應該在旋轉的中間位置,即取到最小值,因此公式為
這里給出為奇數時用三分的方法尋找最小值的過程
用兩個向量X,Y
追蹤旋轉過程中最小覆蓋正方形邊長的變化,正方形的邊長就等于
題解
#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define endl '\n'
#define pi acos(-1)
typedef long long ll;
const int INF = 1 << 30;
const double eps = 1e-8;
struct Point { // 點類
double x, y;
Point() {};
Point(double x, double y): x(x), y(y) {}
void operator=(const Point&a) {
x = a.x, y = a.y;
}
};
typedef Point Vector;
double Dot(Vector A, Vector B) {return A.x * B.x + A.y * B.y;}
double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x;}
double Len(Vector A) {return sqrt(Dot(A, A));} // 向量長度
Vector Rotate(Vector A, double rad)
// 向量逆時針旋轉
{
return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad));
}
int n;
Vector X, Y; // 分別監測旋轉過程中x,y的最小最大值
double cal(double rad)
// 計算旋轉后最小正方形邊長
{
Vector tempx = Rotate(X, rad);
Vector tempy = Rotate(Y, rad);
return max(tempx.x, tempy.y) * 2;
}
double tsearch(double left, double right)
{
double ans = INF;
double mid, midmid;
while (right - left > eps) {
mid = (left + right) / 2;
midmid = (mid + right) / 2;
double ans1 = cal(mid), ans2 = cal(midmid);
if (ans1 < ans2) {
right = midmid;
ans = min(ans, ans1);
}
else {
left = mid;
ans = min(ans, ans2);
}
}
return ans;
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0);
int t; cin >> t;
while (t--) {
cin >> n;
X.x = 0.5 / sin(pi / (2 * n)), X.y = 0;
Y.x = 0.5, Y.y = 0.5 / tan(pi / (2 * n));
double sta = 0, end = pi / (2 * n); // 旋轉范圍
cout << fixed << setprecision(8) << tsearch(sta, end) << endl;
}
return 0;
}
D. Multiset【二分答案】
題目
給定一個具有個元素的集合,有次操作,每次操作給定一個整數,規則如下:
- 如果,則把加入集合中;
- 如果,則從集合中按升序排序后,移除第個元素
如果最終集合非空,輸出任一集合中元素即可
- Memory limit: 28mb
題解
本題可以選擇用線段樹之類的數據結構來模擬題目中的操作,但需要進行一定的優化,因為本題空間限制非常嚴格。
實際上,考慮到最終只需要輸出集合中的任意一個元素即可,不妨假設要輸出最小的一個,那么可以用二分答案的方法來查找。
二分查找的思路為:
定義函數count(x)
表示:對于元素x
,最終集合中小于等于x
的元素個數。
最終答案就應該是找到一個最小的x
滿足
因為在本題中,集合中元素不唯一,并且不一定是連續的。
假設最終集合中最小的元素是y
,那么在二分過程中,任何大于等于y
的數返回結果都是,而比y
小的數返回結果都是0,因此y
就是那個滿足count(x)>0
的最小元素
對于最終集合為空的情況,可以用一個非常大的數去檢驗。因為集合中元素,如果最終集合中小于等于的元素為0,就說明集合中不可能存在任何元素。(如果,就說明最終集合中的最小元素必定是大于的,而這與集合中元素相矛盾)
if (count(int(1e9)) == 0) {
cout << 0 << endl;
}
代碼
#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define endl '\n'
typedef long long ll;
const int maxn = 1e6 + 10;
int n, q;
vector<int>a, k;
int count(int x)
// 計算最終集合里面小于等于x的元素個數
{
int cnt = 0;
for (int i = 0; i < n; i++) { // 初始化
if (a[i] <= x) cnt++;
}
for (int i = 0; i < q; i++) {
if (k[i] > 0 && k[i] <= x) cnt++; // 插入正數,并且比x小,必然會排在x前面
if (k[i] < 0 && abs(k[i]) <= cnt) cnt--; // 插入負數,如果其絕對值<=cnt,就會刪除x左側的元素
}
return cnt;
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> q;
a.resize(n); k.resize(q);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
for (int i = 0; i < q; i++) {
cin >> k[i];
}
if (count(int(1e9)) == 0) { // 判斷最終集合是否為空
cout << 0 << endl;
return 0;
}
int left = 1, right = int(1e6) + 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (count(mid) <= 0) left = mid + 1;
else right = mid;
}
cout << right << endl;
return 0;
}
智能推薦
Codeforces Round #432 題解
比賽鏈接:http://codeforces.com/contest/851 A. Arpa and a research in Mexican wave 題意:balabala 解法:找個規律。。 B. Arpa and an exam about geometry 題意:給你3個點的坐標,問你是否能找到一個點,以該點為中心旋轉一定的角度使得a與b重合,b與c重合 解法:直接判斷只要兩個線段長度...
Codeforces Round #621題解
A、 Cow and HaybalesCow\ and\ HaybalesCow and Haybales 貪心模擬題。 B、 Cow and FriendCow\ and\ FriendCow and Friend 問最少幾步,根據三角形定理知道若以a為步長,跳兩步可組成(0,2a]之間任意值。 1.a<=x時...
Codeforces Round #564 題解
A. Nauuo and Cards time limit per test 1.5 seconds memory limit per test 256 megabytes input standard input output standard output Nauuo is a girl who loves playing cards. One day she was playing card...
freemarker + ItextRender 根據模板生成PDF文件
1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...
猜你喜歡
電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!
Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...
requests實現全自動PPT模板
http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...
Linux C系統編程-線程互斥鎖(四)
互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...
統計學習方法 - 樸素貝葉斯
引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...