ural History Exam 二分
1 #include <iostream> 2 #include <cstdlib> 3 using namespace std; 4 5 //二分查找 6 bool binarySearch(long a[], long x, int n){ 7 int left = 0,right = n-1; 8 int middle; 9 while (left <= right){ 10 middle = (left+right)/2; 11 if (x == a[middle]) return 1; 12 if (x > a[middle]) left = middle + 1; 13 else right = middle - 1; 14 } 15 return 0; 16 } 17 18 int cmp(const void *a, const void *b) { 19 return *(int *)a - *(int *)b; 20 } 21 22 int main(){ 23 int numprofessor; 24 scanf("%ld",&numprofessor); 25 26 long yearProfessor[numprofessor]; 27 for(int i=0;i<numprofessor;i++){ 28 scanf("%ld",&yearProfessor[i]); 29 } 30 31 qsort(yearProfessor,numprofessor,sizeof(long),cmp); 32 long numstudent; 33 scanf("%ld",&numstudent); 34 35 long result=0; 36 37 long yearstudent[numstudent]; 38 for(int i=0;i<numstudent;i++){ 39 scanf("%ld",&yearstudent[i]); 40 if( binarySearch(yearProfessor, yearstudent[i], numprofessor)){ 41 result++; 42 } 43 44 } 45 46 cout<<result; 47 48 }
二分
ural Fibonacci Sequence
第一遍用递归写,结果在数据比较大时,超时了。题目要求1000ms,测试结果是1029ms,代码如下:
1 #include <iostream> 2 using namespace std; 3 4 int i,j,fi,fj,n; 5 int count=0,count1=0,count2=0; 6 int finext; // 表示fi下一个f(i+1)的值 7 8 int fib1(int j){ /*递归程序1:计算fj时用到的fi和finext的次数 */ 9 if(j==i){ 10 count1++; //记录fi用到的次数 11 return 1; 12 } 13 if(j==i+1){ 14 count2++; //记录finext用到的次数 15 return 1; 16 } 17 return fib1(j-1) + fib1(j-2); 18 } 19 20 long fib3 (int n){ 21 //* 迭代解法:这里算法复杂度显然为O(n) , 22 // 这个解法目前来看是最好的解法,算法既不复杂,而且在时间复杂度和空间复杂度上都有保证 23 if(n==i){ 24 return fi; 25 } 26 if(n==i+1){ 27 return finext; 28 } 29 long long x = fi, y = finext; 30 for (int a= i; a<n-1; a++){ 31 y = x + y; 32 x = y - x; 33 } 34 return y; 35 } 36 37 int main(){ 38 cin>>i>>fi>>j>>fj>>n; 39 if(j<i){ 40 int temp=j,temp1=fj; 41 j=i; 42 fj=fi; 43 i=temp; 44 fi=temp1; 45 } 46 int a=fib1(j); 47 finext=(fj-count1*fi)/count2; 48 cout<<fib3(n)<<endl; 49 50 }
回想了一下最近学习的二分法,发现暴力枚举后得二分优化,貌似可以过,遂有下代码:
1 #include <iostream> 2 using namespace std; 3 4 const long long NLAR = 2000000000; 5 long long i,fi,j,fj,n; 6 7 int main(){ 8 cin >> i >> fi >> j >> fj >> n; 9 if(j<i){ //保证j>i 10 int temp=j,temp1=fj; 11 j=i; 12 fj=fi; 13 i=temp; 14 fi=temp1; 15 } 16 17 // cal f[i+1] 18 19 long long left=-NLAR, right=NLAR, mid; 20 long long ti=fi, tj=mid, t; 21 while (left+1<right){ 22 mid = (left+right)/2; 23 ti=fi; tj=mid; 24 for (int k=i+2; k<=j; ++k){ 25 t=ti+tj; 26 ti=tj; 27 tj=t; 28 if(t>NLAR*2 ||t<-NLAR*2) break; 29 } 30 if(tj>=fj) right = mid; 31 else left=mid; 32 } 33 34 ti=fi; tj=right; 35 if(n>i){ 36 for(int k=i+2;k<=n;++k){ 37 t=ti+tj; 38 ti=tj; 39 tj=t; 40 } 41 cout << tj << endl; 42 } 43 else { 44 for(int k=i-1; k>=n; ++k){ 45 t=tj-ti; 46 tj=ti; 47 ti=t; 48 } 49 cout << ti << endl; 50 } 51 52 return 0; 53 }
三分法主要求解单峰函数极值,
ural Bookshelf
本题目中要求的函数的图像(取H=6,h=1)为:可以看出这是一个单峰函数,可以运用三分法求极值。
1 #include <iostream> 2 #include <cstdlib> 3 #include <iomanip> 4 #include <cmath> 5 using namespace std; 6 #define EPS 1e-9 7 8 int h,H,L; 9 double fx(double x){ 10 return H/2.0*x/sqrt(h*h+x*x)-x; 11 } 12 13 int main(){ 14 cin>>h>>H>>L; 15 double left=0,right=H; 16 long double isover=1; 17 18 while(isover>EPS){ 19 double m1=left+(right-left)/3; 20 double m2=right-(right-left)/3; 21 22 double fm1=fx(m1); 23 double fm2=fx(m2); 24 25 if(fm1<fm2) left=m1; 26 else right=m2; 27 isover=right-left; 28 } 29 cout<<fixed<<setprecision(6)<<fx(right)<<endl; 30 }
这里再收录一个关于二分法的课堂例题,poj1064
1 /* 2 * poj-1064 Cable master.cpp 3 * 二分, 化为整数存储,下界为1(cm),上界为最长绳的长度 4 * 5 */ 6 #include<cstdio> 7 using namespace std; 8 9 const double eps = 1e-7; //注意精度 10 const int maxn = 10000 + 10; 11 12 int n, k, cable[maxn]; 13 14 int main(){ 15 scanf("%d%d", &n, &k); 16 double ftmp; 17 int tmpMax = 0; 18 for(int i=0; i<n; i++){ 19 scanf("%lf", &ftmp); 20 cable[i] = int((ftmp+eps) * 100); //精度 21 22 if(cable[i] > tmpMax) tmpMax = cable[i]; 23 } 24 25 int up = tmpMax, low = 1, mid = -1, ans = -1; 26 int tmpNum = 0; 27 while(low <= up){ 28 mid = (up + low) / 2; 29 tmpNum = 0; 30 for(int i=0; i<n; i++) 31 tmpNum += cable[i] / mid; 32 33 if(tmpNum >= k){ 34 if(mid > ans) ans = mid; 35 low = mid + 1; 36 } 37 else 38 up = mid - 1; 39 } 40 41 if(ans < 1) 42 printf("0.00 "); 43 else 44 printf("%.2lf ", ans * 0.01); 45 46 47 return 0; 48 }