方法 : binary search
题意 : 寻找在题目提供的ap数量下 半径最小值
做法 : Binary Serach
因为房子一定要被包到 所以可以假设房子刚好被ap覆盖到的情况下之最少距离
因此以房子为準依直径向外扩张 最后题目所求的半径再用所得直径/2即得
标签:
在计算机科学中,折半搜索(英语: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 }
循环版:
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 }
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 }
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 }
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 }
使用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 }
uva,11516
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 }
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 }
标签:
原文地址:http://www.cnblogs.com/do-it-best/p/5364894.html