Date:2019-07-25 16:03:14
算法实现
1 /*---------------------------有序数组中查找给定数字x-------------------------*/
2 #include <stdio.h>
3
4 //left=0, right=n-1
5 int binarySearch(int A[], int left, int right, int x)
6 {
7 int mid; //mid为left和right的中点
8 while(left <= right)
9 {
10 //
11 // 若right超过int型上界的一半,则left+right可能溢出
12 // mid = left + (right - left)/2; 替代
13 //
14 mid = (left+right) / 2;
15
16 if(A[mid] == x)
17 {
18 return mid;
19 }
20 else if(A[mid] > x) //中间数大于x,则往左区间查找
21 {
22 right = mid - 1;
23 }
24 else //中间数小于x,则往右区间查找
25 {
26 left = mid + 1;
27 }
28 }
29
30 return -1; //查找失败,返回-1
31 }
32
33 int main(void)
34 {
35 const int n = 10;
36 int A[n] = {1, 3, 4, 6, 7, 8, 10, 11, 12, 15};
37 printf("%d %d\n", binarySearch(A,0,n-1,6), binarySearch(A,0,n-1,9));
38 /*
39 output:
40 3 -1
41 */
42
43 return 0;
44 }
45
46 /*----------------------求序列中的第一个大于等于x的元素的位置-------------------*/
47
48 //left=0, right=n
49 int lower_bound(int A[], int left, int right, int x)
50 {
51 int mid;
52 while(left < right) //当left==right时,找到该位置
53 {
54 mid = left + (right-left)/2;
55 if(A[mid] >= x)
56 {
57 right = mid;
58 }
59 else
60 {
61 left = mid + 1;
62 }
63 }
64
65 //
66 // 若所有元素均大于x,则返回left的值为0,即x应插入的位置是A[0]
67 // 若所有元素均小于x,则返回left的值为n,即x应插入的位置是A[n]
68 //
69 return left;
70 }
71
72 /*---------------------求序列中第一个大于x的元素位置---------------------------*/
73
74 //left=0, right=n
75 int upper_bound(int A[], int left, int right, int x)
76 {
77 int mid;
78 while(left < right)
79 {
80 mid = left + (right-left)/2;
81 if(A[mid] <= x)
82 {
83 left = mid + 1;
84 }
85 else
86 {
87 right = mid;
88 }
89 }
90
91 return left;
92 }
93
94 /*-------------------------------计算根号2的近似值-----------------------------*/
95 const double eps = 1e-5; //精度为10^-5
96
97 double f(double x)
98 {
99 return x*x;
100 }
101
102 double calSqrt()
103 {
104 double left=1, right=2, mid;
105 while(right - left > eps)
106 {
107 mid = left + (right-left)/2;
108 if(f(mid) > 2)
109 {
110 right = mid;
111 }
112 else
113 {
114 left = mid;
115 }
116 }
117
118 return mid;
119 }
120
121 /*--------------给定一个定义在[L,R]上的单调函数f(x),求方程f(x)=0的根-----------*/
122 const double eps = 1e-1;
123
124 double f(double x)
125 {
126 return /*f(x)*/;
127 }
128
129 double solve(double L, double R)
130 {
131 double left=L, right=R, mid;
132 while(right-left < eps)
133 {
134 if(f(mid) < 0)
135 {
136 left = mid;
137 }
138 else
139 {
140 right = mid;
141 }
142 }
143
144 return mid;
145 }
146
147 /*-----------------------------装水问题---------------------------*/
148 /*
149 问题描述:
150 有一个侧面看去是半圆的储水装置,该半圆的半径为R,要求往里面装入高度为h的水,使其
151 侧面看去的面积S1与半圆面积S2的比例恰好为r。现给定R和r,求高度h。
152 */
153
154 #include <cstdio>
155 #include <cmath>
156
157 const double PI = acos(-1.0);
158 const double eps = 1e-5;
159
160 double f(double R, double h)
161 {
162 double alpha = 2*acos((R-h)/R);
163 double L = 2*sqrt(R*R-(R-h)*(R-h));
164 double S1 = alpha*R*R/2 - L*(R-h)/2;
165 double S2 = PI*R*R/2;
166
167 return S1/S2;
168 }
169
170 double solve(double R, double r)
171 {
172 double left=0, right=R, mid;
173 while(right - left > eps)
174 {
175 mid = left + (right-left)/2;
176 if(f(R, mid) < r)
177 {
178 left = mid;
179 }
180 else
181 {
182 right = mid;
183 }
184 }
185
186 return mid;
187 }
188
189 int main(void)
190 {
191 double R, r;
192 scanf("%lf%lf", &R, &r);
193
194 printf("%.4f\n", solve(R, r));
195
196 return 0;
197 }
198
199 /*----------------------------木棒切割问题---------------------------*/
200 /*
201 问题描述:
202 给出N根木棒,长度均已知,现在希望通过切割它们来得到至少K段长度相等的木棒(长度必须是整数),
203 问这些长度相等的木棒最长能有多长
204 输入样例:
205 3 7
206 10 15 24
207 输出样例:
208 6
209 */
210 #include <stdio.h>
211 #include <algorithm>
212
213 using namespace std;
214
215 const int MAX_SIZE = 100010;
216
217 int wood[MAX_SIZE];
218
219 int number(int len, int n)
220 {
221 int ans=0;
222 for(int i=0; i<n; i++)
223 {
224 ans += wood[i]/len;
225 }
226
227 return ans;
228 }
229
230 int main(void)
231 {
232 int n, k;
233 scanf("%d%d", &n, &k);
234
235 for(int i=0; i<n; i++)
236 {
237 scanf("%d", &wood[i]);
238 }
239
240 sort(wood, wood+n);
241
242 /*
243 随着每段木棒长度的增加,获得最大段数的木棒数递减
244 即所求最后一个段数大于等于k的点,对应的长度即为所求
245 即if(number(mid,n) >= k),这样的判定条件会出现死循环
246 可以转化为,求第一个长度小于k的点,即if(number(mid,n) > k)
247 */
248 int left=1, right=wood[n-1], mid;
249 while(left < right)
250 {
251 mid = left + (right-left)/2;
252 if(number(mid, n) > k)
253 {
254 left = mid + 1;
255 }
256 else
257 {
258 right = mid;
259 }
260
261 }
262
263 printf("%d\n", left);
264
265 return 0;
266 }
267
268 /*-------------------------------快速幂-------------------------------*/
269 /*
270 问题描述:
271 求a^b,采用循环for(i=0; i<b; i++){ans *= a;},时间复杂度为O(b)
272 当b = 10^8甚至更大时,时间效率很低
273 因此,可以采用二分法达到O(logb)的时间复杂度
274
275 试求,a^b % m 的结果
276 */
277
278 //
279 // 递归写法
280 //
281 typedef long long LL;
282
283 LL binaryPow(LL a, LL b, LL m)
284 {
285 if(b == 0)
286 {
287 return 1; //a^0 = 1
288 }
289
290 // b%2==1 等价于 b&1,即进行位与操作,判断b的末位是否为1,执行速度较快
291 if(b%2 == 1) //b为奇数
292 {
293 return a * binaryPow(a, b-1, m) % m;
294 }
295 else //b为偶数
296 {
297 //此处若return binary()*binary;则时间复杂度会翻倍
298 LL mul = binaryPow(a, b/2, m);
299 return mul*mul%m;
300 }
301 }
302
303 //
304 // 迭代写法
305 //
306 typedef long long LL;
307
308 LL binaryPow(LL a, LL b, LL m)
309 {
310 LL ans=1;
311
312 //b = 13 = 8 + 4 + 1 = 2^3 + 2^2 + 2^0
313 //b = (1 1 0 1)2;
314 while(b > 0)
315 {
316 if(b&1) //b的二进制个位==1, ans累乘
317 {
318 ans *= a % m;
319 }
320
321 a = a * a % m;
322 b >>= 1; //将b的二进制右移1位,即b=b>>1或b=b/2;
323 }
324
325 return ans%m;
326 }
来源:https://www.cnblogs.com/blue-lin/p/11244910.html