大一寒假集训 二分入门

A - Cable master HDU - 1551 

题目大意:求最大长度,使得每段铁丝截得的段数等于给出的k值。

 1 #include<algorithm>
 2 #include <iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<cmath>
 6 using namespace std;
 7 const int maxn = 100000 + 15;
 8 double arr[maxn];
 9 int n, k;
10 bool solve(double mid) {
11     long long int ans = 0;
12     for (int i = 0;i < n;i++) {
13         ans =ans+(int)(arr[i] / mid);
14     }
15     if (ans >= k)return true;
16     else return false;
17 }
18 int main() {
19     while (scanf("%d %d", &n, &k), n + k) {
20         double max = 0;
21         for (int i = 0;i < n;i++) {
22             scanf("%lf", &arr[i]);
23             if (arr[i] > max)max = arr[i];
24         }
25         double left = 0, right = max, mid;
26         while (right-left>1e-5) {
27             mid = (right + left) / 2;
28             if (solve(mid)) { left = mid; }
29             else right = mid;
30         }
31         printf("%.2f\n", left);//注意是left,因为mid不一定满足
32     }
33 
34     return 0;
35 }
View Code

B - Dating with girls(1) HDU - 2578

题目大意:求给出数列中任意选两数之和为k的对数。前后可以交换。

 1 #include<algorithm>
 2 #include <iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<cmath>
 6 using namespace std;
 7 const int maxn = 100000 + 15;
 8 int n, k;
 9 int arr[maxn];
10 int main() {
11     int t;
12     scanf("%d", &t);
13     while (t--) {
14         scanf("%d %d", &n, &k);
15         for (int i = 0;i < n;i++) {
16             scanf("%d", &arr[i]);
17         }
18         sort(arr, arr + n);
19         int num = unique(arr, arr + n) - arr;//去重
20         int ans = 0;
21         for (int i = 0;i < num;i++) {
22             int need = k - arr[i];
23             if (2 * arr[i] == k) { ans++;break; }
24             else if (2 * arr[i] > k) { break; }
25             int left = i, right = num - 1, mid;
26             while (right >= left) {
27                 mid = (right + left) / 2;
28                 if (arr[mid] < need)left = mid + 1;
29                 else if(arr[mid] > need)right = mid - 1;
30                 else if (arr[mid] == need) { ans+=2;break; }
31             }
32         }
33         printf("%d\n", ans);
34     }
35     return 0;
36 }
View Code

C - Pie POJ - 3122  简单的二分,π是坑点

题目大意:给出蛋糕半径,分蛋糕,且每人份只能取自一个蛋糕。

 1 #include<algorithm>
 2 #include <iostream>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<cmath>
 6 #define pi acos(-1)
 7 using namespace std;
 8 const int maxn = 100000 + 15;
 9 int n, f;
10 double arr[maxn];
11 bool solve(double mid) {
12      int ans = 0;
13     for (int i = 0;i < n;i++) {
14         ans +=(int)(arr[i] / mid);
15     }
16     if (ans >= f + 1)return true;
17     else return false;
18 }
19 int main() {
20     int t;
21     scanf("%d", &t);
22     while (t--) {
23         double left = 0, right=0, mid;
24         scanf("%d %d", &n, &f);
25         for (int i = 0;i < n;i++) {
26             scanf("%lf", &arr[i]);
27             arr[i] = arr[i] * arr[i] * pi;
28             if (arr[i] > right)right =arr[i];
29         }
30         while (right - left > 1e-5) {
31             mid = (right + left) / 2;
32             if (solve(mid))left = mid;
33             else right = mid;
34         }
35         printf("%.4f\n", left);
36         
37     }
38     return 0;
39 }
View Code

D - Can you solve this equation? HDU - 2199 

 1 #include <iostream>
 2 #include <map>
 3 #include <string>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<cmath>
 7 #define max 100010
 8 using namespace std;
 9 int a[max];
10 double judge(double x){
11     return 8 * x * x * x * x + 7 * x * x * x + 2 * x * x + 3 * x + 6 ;
12 }
13 int main()
14 {
15     int t;
16     scanf("%d", &t);
17     while (t--) {
18         long long int y;
19         scanf("%d", &y);
20         if (y < 0)y = -y;
21         double left = 0, right = 100;
22         int flag = 0;
23         double mid;
24         while (right >left) {
25              mid = (left + right) / 2;
26             if (fabs(judge(mid) - y) < 1e-5) {
27                 flag = 1;break;
28             }
29             if (judge(mid) - y > 0)right = mid;
30             else left = mid;
31         }
32         if (flag == 0)printf("No solution!\n");
33         else printf("%.4f\n", mid);
34     }
35 }
View Code

E - Rikka with Mutex HDU - 6261   二分,strlen放在for循环中会超时

题目大意:给定一串字符串由V和P组成,一个人的初始生命值为0,遇V+1,遇P-1,同伴中可以分享生命值,在保证生命值不为负的情况下,求最少需要多少人,能让一个人走到终点。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn = 1e5 + 10;
 6 char str[maxn];
 7 bool solve(int mid) {
 8     int life = 0, step = 0;
 9     int len = strlen(str);
10     for (int i = 0;i < len;i++) {
11         if (str[i] == 'P') { step--;}
12         else step++;
13         if (step > 0) {
14             step = 0;life += mid;;
15         }
16         if (life+step< 0)return false;
17     }
18     return true;
19 }
20 int main() {
21     int t;
22     scanf("%d", &t);
23     while (t--) {
24         scanf("%s", str);
25         int len = strlen(str);
26         if (str[0] == 'P') { printf("-1\n");continue; }
27         int left = 0, right = len, mid;
28         int ans;
29         while (right >= left) {
30             mid = (left + right) / 2;
31             if (solve(mid)) {
32                 ans = mid;right = mid - 1;
33             }
34             else left = mid + 1;
35         }
36         printf("%d\n", ans);
37     }
38     return 0;
39 }
View Code

F - Aggressive cows POJ - 2456  二分

 题目大意:给出n个牛舍坐标(在一直线上),然后有m个牛要入住,现在问相邻牛之间的最小距离最大是几 ,通俗的说就是一条线段上有 n 个点,选取 m 个点,使得相邻点之间的最小距离值最大。

 1 #include <iostream>
 2 #include <map>
 3 #include<cstdio>
 4 #include <string>
 5 #include<algorithm>
 6 #include<vector>
 7 #include<cmath>
 8 #define maxn 100010
 9 int arr[maxn],b[maxn],bj=0,n,c;
10 using namespace std;
11 bool solve(int mid) {
12     int cnt = 0,add=0;
13     for (int i = 0;i < bj;i++) {
14         add += b[i];
15         if (add >= mid) { cnt++;add = 0; }
16     }
17     if (cnt >= c - 1)return true;
18     return false;
19 }
20 int main()
21 {
22     scanf("%d %d", &n, &c);
23     for (int i = 0;i < n;i++) {
24         scanf("%d", &arr[i]);
25     }
26     sort(arr, arr + n);
27     int right = 0;
28     for (int i = 1;i < n;i++) {
29         b[bj++] = arr[i] - arr[i - 1];
30         right += b[bj - 1];
31     }
32     int left = 0, mid,res;
33     while (right >= left) {
34         mid = (right + left) / 2;
35         if (solve(mid)) {
36             res = mid;left = mid + 1;
37         }
38         else right = mid - 1;
39     }
40     printf("%d\n", res);
41 }
View Code

G - 4 Values whose Sum is 0 POJ - 2785 

题目大意:每列选一个看能否组成和为0.

 1 #include <iostream>
 2 #include <map>
 3 #include <string>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<cstdio>
 7 #include<cmath>
 8 using namespace std;
 9 vector<int>a,b,c,d,e,f;
10 int main()
11 {
12     int n;
13     scanf("%d", &n);
14     for (int i = 0;i < n;i++) {
15         int a1, b1, c1, d1;
16         scanf("%d %d %d %d", &a1, &b1, &c1, &d1);
17         a.push_back(a1);b.push_back(b1);c.push_back(c1);d.push_back(d1);
18     }
19     for (int i = 0;i < n;i++) { for (int j = 0;j < n;j++) { e.push_back(a[i] + b[j]); } }
20     for (int i = 0;i < n;i++) { for (int j = 0;j < n;j++) { f.push_back(c[i] + d[j]); } }
21     sort(f.begin(), f.end());
22     int cnt = 0;
23     for (int i = 0;i < e.size();i++) {
24         int left = 0, right = f.size()-1, mid;
25         while (right >= left) {
26             mid = (left + right) / 2;
27             if (e[i] + f[mid] > 0)right = mid - 1;
28             else if (e[i] + f[mid] < 0)left = mid + 1;
29             else {
30                 cnt++;
31                 for (int j = mid + 1;j < f.size();j++) {
32                     if (e[i] + f[j] == 0) { cnt++; }
33                     else break;
34                 }
35                 for (int j = mid - 1;j >= 0;j--) {
36                     if (e[i] + f[j] == 0) { cnt++; }
37                     else break;
38                 }
39                 break;
40             }
41         }
42     }
43     printf("%d\n", cnt);
44 }
View Code

 

posted @ 2020-02-08 10:13  programmer_w  阅读(0)  评论(0)    收藏  举报