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