binary_search算法

计算机科学中,折半搜索英语:half-interval search),也称二分查找算法binary search)、二分搜索法二分搜索二分探索,是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。这种搜索算法每一次比较都使搜索范围缩小一半。

 

递归版:

 1 int binary_search(const int arr[],int start,int end,int key)
 2 {
 3     if(start>end)
 4         return -1;
 5     int mid=start+(end-start)/2;
 6     if(arr[mid]>key)
 7         return binary_search(arr,start,mid-1,key);
 8     if(arr[mid]<key)
 9         return binary_search(arr,mid+1,end,key);
10     return mid;
11 }
View Code

循环版:

 1 int binary_search(const int arr[],int start,int end,int key)
 2 {
 3     while(start<=end)
 4     {
 5         int mid=start+(end-start)/2;
 6         if(arr[mid]>key)
 7             end=mid-1;
 8         else if(arr[mid]<key)
 9             start=mid+1;
10         else
11             return mid;
12     }
13     return -1
14 }
View Code

uva,10077 结构体单次打表的妙处

 1 #include <iostream>
 2 #include <cstdio>
 3 
 4 using namespace std;
 5 
 6 struct fraction
 7 {
 8     int x;
 9     int y;
10 };
11 
12 int main()
13 {
14     int m,n;
15     while(scanf("%d %d",&m,&n))
16     {
17         if(m==1 && n==1) break;
18         fraction L={0,1},M={1,1},R={1,0};
19         while(1)
20         {
21         long double t1=(long double)m/n,t2=(long double)M.x/M.y;
22         if(t1<t2)
23         {
24             printf("L");
25             R=M;
26             M.x+=L.x;
27             M.y+=L.y;
28         }
29         else if(t1>t2)
30         {
31             printf("R");
32             L=M;
33             M.x+=R.x;
34             M.y+=R.y;
35         }
36         else
37         {
38             printf("\n");
39             break;
40         }
41         }
42     }
43     return 0;
44 }
View Code

uva,10706

//注意1-9之后10算两位数字,所以分数组的时候不是等差。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <cctype>
 5 #include <string.h>
 6 #define maxn 2147483647
 7 using namespace std;
 8 
 9 int K;
10 char b[1000000];
11 long long sum[100000];
12 
13 int pan(int x)
14 {
15     int n=0;
16     while(x)
17     {
18         x/=10;
19         n++;
20     }
21     return n;
22 }
23 
24 void init()
25 {
26     int a;
27     K=sqrt(maxn)+1;
28     int j=1;
29     for(int i=1;i<=K;i++)
30     {
31         sprintf(&b[j],"%d",i);
32         while(isdigit(b[j]))
33             j++;
34     }
35     a=sum[0]=0;
36     for(int i=1;i<=K;i++)
37     {
38         a+=pan(i);
39         sum[i]=sum[i-1];
40         sum[i]+=a;
41     }
42 }
43 
44 int main()
45 {
46     int min,max,mid,k;
47     init();
48     int t,i;
49     scanf("%d",&t);
50     while(t--)
51     {
52         min=0;max=K;
53         scanf("%d",&i);
54         while(1)
55         {
56             mid=min+(max-min)/2;
57             if(mid==min)
58                 break;
59             if(sum[mid]>=i)
60                 max=mid;
61             else
62                 min=mid;
63         }
64         i-=sum[mid];
65         printf("%c\n",b[i]);
66     }
67     return 0;
68 }
View Code

HDU,4282 具体详解

//这类型题目确定两个值,二分搜索第三个。学会确定上下限。z<32,x,y<2^15

 1 #include <iostream>
 2 #include <cstdio>
 3 
 4 using namespace std;
 5 typedef long long ll;
 6 
 7 int ans,k;
 8 
 9 ll Pow(ll x,ll y)
10 {
11     long long tmp=x;
12     for(long long i=1;i<y;i++)
13         x*=tmp;
14     return x;
15 }
16 
17 void solve()
18 {
19     ans=0;
20     ll mid,l,r,tmp;
21     for(int z=2;z<32;z++)
22     {
23         for(int x=1;x<50000;x++)
24         {
25             if(Pow(x,z)>=k/2) break;
26             l=x+1;r=50000;
27             while(l<=r)
28             {
29             mid=(l+r)>>1;
30             tmp=Pow(x,z)+Pow(mid,z)+x*mid*z;
31             if(tmp==k)
32             {
33                 ans++;
34                 break;
35             }
36             else if(tmp>k || tmp<0)
37                 r=mid-1;
38             else
39                 l=mid+1;
40             }
41             
42         }
43     }
44     printf("%d\n",ans);
45 }
46 
47 int main()
48 {
49     while(scanf("%d",&k) && k)
50     {
51         solve();
52     }
53     return 0;
54 }
View Code

 

 

使用binary_search的思想:找到left  和right分别是什么  具体详解

uva,11413

 1 #include <cstdio>
 2 
 3 using namespace std;
 4 
 5 int M,N;
 6 int n[1000001];
 7 
 8 int main()
 9 {
10     while(scanf("%d %d",&M,&N)!=EOF)
11     {
12         int left=0,right=0,mid;
13         for(int i=0;i<M;i++)
14         {
15             scanf("%d",&n[i]);
16             if(n[i]>left) left=n[i];
17             right+=n[i];
18         }
19         
20         while(left<right)
21         {
22             mid=(left+right)>>1;
23             int amount=0,sum=0;
24             for(int i=0;i<M;i++)
25             {
26                 sum+=n[i];
27                 if(sum>mid)
28                 {
29                     amount++;
30                     sum=n[i];
31                 }
32                 else if(sum==mid)
33                 {
34                     amount++;
35                     sum=0;
36                 }
37             }
38             if(sum>0)
39                 amount++;
40             if(amount>N) left=mid+1;
41             else
42                 right=mid;
43         }
44         printf("%d\n",left);
45     }
46     return 0;
47 }
View Code

uva,11516

方法 : binary search

题意 : 寻找在题目提供的ap数量下 半径最小值

做法 : Binary Serach 

因为房子一定要被包到 所以可以假设房子刚好被ap覆盖到的情况下之最少距离
因此以房子为準依直径向外扩张 最后题目所求的半径再用所得直径/2即得 
 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 int loc[100005];
 6 
 7 int main()
 8 {
 9     int tc;
10     scanf("%d",&tc);
11     while(tc--)
12     {
13         int s,h,i,lo,hi,mid;
14         scanf("%d %d",&s,&h);
15         for(i=0;i<h;i++)
16             scanf("%d",&loc[i]);
17         sort(loc,loc+h);
18         lo=0;
19         hi=2*(loc[h-1]-loc[0]+1);
20         while(hi>lo)
21         {
22             mid=(lo+hi)/2;
23             int start=loc[0];
24             int needed=1;
25             for(i=1;i<h;i++)
26                 if(loc[i]>start+mid)
27                 {
28                     needed++;
29                     start=loc[i];
30                 }
31             if(needed>s)
32                 lo=mid+1;
33             else
34                 hi=mid;
35         }
36         printf("%.1f\n",hi/2.00);
37     }
38     return 0;
39 }
View Code

uva,10539

题目先用线筛法打表,然后用前缀和法相减就可以了。

注意题目意思:非质数且只能整除一个质数,即是一个质数的n次方。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #define maxn 1000000
 5 using namespace std;
 6 typedef long long ll;
 7 int prime[maxn];
 8 int isprime[maxn+5];
 9 int ans;
10 ll low,high;
11 void Prime()
12 {
13     ans=0;
14     memset(isprime,1,sizeof(isprime));
15     for(int i=2;i<=maxn;i++)
16     {
17         if(isprime[i])  prime[ans++]=i;
18         for(int j=0,tmp;j<ans && (tmp=i*prime[j])<=maxn;j++)
19         {
20             isprime[tmp]=0;
21             if(!(i%prime[j])) break;
22         }
23         
24     }
25 }
26 
27 ll solve(ll n)
28 {
29     ll count=0;
30     for(int i=0;i<ans;i++)
31     {
32         ll u=prime[i]*prime[i];
33         if(u>n)
34             break;
35         while(u<=n)
36         {
37             u*=prime[i];
38             count++;
39         }
40     }
41     return count;
42 }
43 
44 
45 int main()
46 {
47     int N;
48     Prime();
49     scanf("%d",&N);
50     while(N--)
51     {
52         scanf("%lld %lld",&low,&high);
53         printf("%ld\n",solve(high)-solve(low-1));
54     }
55     return 0;
56 }
View Code

 

posted @ 2016-04-07 18:50  指尖泛出的繁华  阅读(2042)  评论(0编辑  收藏  举报