codeforces#514 Div2---1059ABCD

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 }
View Code

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 }
View Code

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 }
View Code

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 }
View Code
原文地址:https://www.cnblogs.com/wyboooo/p/9959947.html