1059A---Cashier
http://codeforces.com/contest/1059/problem/A
题意:
Vasya每天工作(l)个小时,每天服务(n)个顾客,每个休息时长是(a)。给定(n)个客人来的时间和时长。问Vasya可以休息多长时间。
思路:
先给客人排个序,然后各个间隔除以休息时间之和就是答案。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<set> 10 using namespace std; 11 typedef long long LL; 12 #define N 100010 13 #define pi 3.1415926535 14 15 int n, l, a; 16 const int maxn = 1e5 + 5; 17 struct node{ 18 int l, len; 19 }peo[maxn]; 20 bool cmp(node a, node b) 21 { 22 return a.l < b.l; 23 } 24 25 int main() 26 { 27 while(scanf("%d%d%d", &n, &l, &a) != EOF){ 28 for(int i = 0; i < n; i++){ 29 scanf("%d%d", &peo[i].l, &peo[i].len); 30 } 31 sort(peo, peo + n, cmp); 32 33 int cnt = peo[0].l / a; 34 for(int i = 1; i < n; i++){ 35 cnt += (peo[i].l - peo[i - 1].l - peo[i - 1].len) / a; 36 } 37 cnt += (l - peo[n - 1].l - peo[n - 1].len) / a; 38 printf("%d ", cnt); 39 40 } 41 return 0; 42 }
1059B---Forgery
http://codeforces.com/contest/1059/problem/B
题意:
用笔可以填成下面这样。问能不能画出题目给定的样子。
xxx
x.x
xxx
思路:
每个(.)是的周围八个是不可以作为落笔的中心的。同时边界上的点也不可以作为边界中心。
而对于每一个(#),周围的八个中至少要有一个是可以作为中心的点。
卡了好久啊我的妈。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<set> 10 using namespace std; 11 typedef long long LL; 12 #define N 100010 13 #define pi 3.1415926535 14 15 int n, m; 16 const int maxn = 1005; 17 char g[maxn][maxn]; 18 char graph[maxn][maxn]; 19 bool forbidden[maxn][maxn]; 20 //int mvx[4] = {-1, 1, 0, 0}; 21 //int mvy[4] = {0, 0, -1, 1}; 22 23 bool inside(int i, int j) 24 { 25 return i >= 1 && j >= 1 && i <= n && j <= m; 26 } 27 28 int main() 29 { 30 while(scanf("%d%d", &n, &m) != EOF){ 31 memset(forbidden, 0, sizeof(forbidden)); 32 for(int i = 1; i <= n; i++){ 33 scanf("%s", g[i] + 1); 34 for(int j = 1; j <= m; j++){ 35 //graph[i][j] = '.'; 36 if(g[i][j] == '.'){ 37 for(int dx = -1; dx <= 1; dx++){ 38 for(int dy = -1; dy <= 1; dy++){ 39 if(dx == 0 && dy == 0 || !inside(i + dx, j + dy))continue; 40 forbidden[i + dx][j + dy] = true; 41 } 42 } 43 } 44 } 45 } 46 47 bool flag = true; 48 for(int i = 1; i <= n; i++){ 49 for(int j = 1; j <= m; j++){ 50 if(g[i][j] == '#'){ 51 int cnt = 0; 52 for(int dx = -1; dx <= 1; dx++){ 53 for(int dy = -1; dy <= 1; dy++){ 54 if(dy == 0 && dx == 0 || !inside(i + dx, j + dy))continue; 55 if(i + dx == 1 || i + dx == n || j + dy == 1 || j + dy == m)continue; 56 else if(!forbidden[i + dx][j + dy])cnt++; 57 } 58 } 59 if(cnt == 0){ 60 flag = false; 61 break; 62 } 63 } 64 } 65 if(!flag)break; 66 } 67 if(flag){ 68 printf("YES "); 69 } 70 else{ 71 printf("NO "); 72 } 73 } 74 return 0; 75 }
1059C---Sequence Transformation【递归】
http://codeforces.com/contest/1059/problem/C
题意:
给定一个(1~n)的序列,每一次求得这个序列中所有数的最小公因数,然后随机删掉一个。问怎样删可以使得得到的答案序列是字典序最大的。
思路:
因为给定的是(1~n)连续的整数,相邻两个数之间肯定是互质的。所以刚开始要去掉相邻的数,这部分的答案都是1
显然我们应该要尽量去掉奇数,因为要让字典序最大,就必须要让除1外的其他数尽快出现。删除奇数是最快的。
剩下来的数就是一堆偶数了。比如我们剩下了(2,4,6,8)。他们其实可以看成是(1*2, 2*2, 3*2, 4*2)
将他们除以(2)之后就又是一个(1~4)的子问题了。不断dfs递归下去,直到总数是1、2或3时就可以直接输出答案然后返回了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<set> 10 using namespace std; 11 typedef long long LL; 12 #define N 100010 13 #define pi 3.1415926535 14 15 int n; 16 17 void dfs(int k, int mul) 18 { 19 if(k == 1){ 20 printf("%d ", mul); 21 return; 22 } 23 else if(k == 2){ 24 printf("%d %d ", mul, mul * 2); 25 return; 26 } 27 else if(k == 3){ 28 printf("%d %d %d ", mul, mul, mul * 3); 29 return; 30 } 31 32 for(int i = 0; i < (k + 1) / 2; i++){ 33 printf("%d ", mul); 34 } 35 dfs(k / 2, mul * 2); 36 37 } 38 39 int main() 40 { 41 while(scanf("%d", &n) != EOF){ 42 dfs(n, 1); 43 printf(" "); 44 } 45 return 0; 46 }
1059D---Nature Reserve【二分】【好题】
http://codeforces.com/contest/1059/problem/D
题意:
给定n个点,要求找到一个最小的圆覆盖这些点,并且这个圆和横坐标轴有且仅有一个交点。输出最小的半径。
思路:
刚开始想了很久的最小圆覆盖,还去学了一下模板。后来发现是不可以用最小圆覆盖的。因为最小圆覆盖得到的圆有可能和横坐标有两个交点。
正解应该是二分半径。
(-1)的情况很简单,只要有点在横坐标两侧或者横坐标上有多于两个点就不可以。
由于和横坐标轴有且仅有一个交点,所以半径一定就是圆心的纵坐标值。
二分半径,然后去看当前半径是不是可以包括所有的点。
这个要怎么判断呢。
假设点$p_{i}$的坐标为$(x_{i}, y_{i})$,当前的半径是$R$
那么圆心$c$的坐标就是$(x, R)$, 其中$x$是一个未知数。
圆心到$p_{i}$的距离要小于等于$R$,我们可以列出一个方程,
求出$x$的取值区间是$[x_{i} - sqrt{R^{2} - (R-y_{i})^{2}}, x_{i} + sqrt{R^{2} - (R-y_{i})^{2}}]$
如果$n$个点的这个区间的交集是空集的话,那么这个半径$R$就是不可行的。
输出搞了超级久,烦人。
1 #include<iostream> 2 #include<bits/stdc++.h> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstdlib> 6 #include<cstring> 7 #include<algorithm> 8 #include<queue> 9 #include<vector> 10 #include<set> 11 using namespace std; 12 typedef long long LL; 13 #define N 100010 14 #define pi 3.1415926535 15 16 const int maxn = 1e5 + 5; 17 const double eps = 1e-8; 18 19 int n; 20 struct node{ 21 double x, y; 22 }p[maxn]; 23 24 bool check(double x) 25 { 26 double l = -1e18, r = 1e18; 27 for(int i = 0; i < n; i++){ 28 if(p[i].y > 2 * x)return 0; 29 double t=sqrt(p[i].y*(2*x-p[i].y)); 30 l = max(l, p[i].x - t); 31 r = min(r, p[i].x + t); 32 } 33 return (l - r + eps) <= 0; 34 } 35 36 int main() 37 { 38 //ios_base::sync_with_stdio(false); 39 while(scanf("%d", &n) != EOF){ 40 bool negative = false, positive = false; 41 int zero = 0; 42 for(int i = 0; i < n; i++){ 43 cin>>p[i].x>>p[i].y; 44 if(p[i].y > 0)positive = true; 45 if(p[i].y < 0){ 46 negative = true; 47 p[i].y = -p[i].y; 48 } 49 if(p[i].y == 0)zero++; 50 } 51 52 if(negative && positive || zero >= 2){ 53 printf("-1 "); 54 } 55 else{ 56 double st = 0.0, ed = 1e18, ans; 57 for(int k = 0; k < 300; k++){ 58 double mid = (st + ed) / 2; 59 if(check(mid)){ 60 ed = mid; 61 } 62 else{ 63 st = mid; 64 } 65 } 66 //cout<<st<<endl; 67 printf("%f ", st);//cout<<ans<<endl; 68 } 69 } 70 return 0; 71 }