强化阶段 Day 14 算法笔记 4.5 二分(2)

目录

1.Perfect Sequence

2.Radix

3.Shopping in Mars

4.Find Coins


1.Perfect Sequence

10的9次方-10的18次方之间的数据就要用long long了,注意两个int相乘最后生成一个long long类型的情况。一定要注意,有的地方用了longlong,结果后面又用int进行计算。

二分其实精髓就在于left和right两个变量,left变量一直代表的都是无法达成目标的位置,而right变量一旦移动,那就代表了满足想要的坐标。所以有时候要特判一下right没有移动的情况,本体就是get_num函数的第二行。

因为要找第一个大于某个数的位置,left之前一直都是代表小于或等于。但是left每次都会加1,所以如果加1只有,left碰到right了,说明找到位置了。

#include<cstdio>
#include<vector>
#include<cstring>
#include<string>
#include<stack>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
#include<iostream>
using namespace std;

long long martix[100005];
long long n;

int get_num(int pos,long long value){
	
	int left=pos,right=n,mid;
	if(martix[n-1]<=value) return n-pos+1;
	while(left<right){
		mid = (left+right)/2;
		if(martix[mid]<=value){
			left=mid+1;
		}else{
			right=mid;
		}
	}
	return right-pos+1;
}

int main(){
	
	long long p;
	scanf("%lld %lld",&n,&p);
	for(int i=0;i<n;i++){
		scanf("%lld",&martix[i]);
	}
	sort(martix,martix+n);
	
	int max_=1,cur;
	for(int i=0;i<n;i++){
		cur=get_num(i+1,martix[i]*p);
		if(cur>max_) max_=cur;
	}
	printf("%d",max_);
	
	
	return 0;
}

2.Radix

这一题也比较复杂,没有完全解决,思路差不多通了。

这个init函数有点意思,这样初始化数组之后后面就很方便。

整个题的大概流程:

首先是把给出进制的那个数转换成十进制数,如果tag是1那就第一个,如果tag是2,那就把1和2交换一下,用到了strcpy函数。

然后就要大概的算下另外一个数的进制的可能的范围。

(1)下界就用这个数所有位中最大的那一位+1;

(2)上界用下界+1和另外一个给出进制数的十进制数+1的最大值作为上界,这个地方要好好琢么一下

最后就通过进制的范围进行二分,找出来正确的进制。二分时就是选择一个mid的进制,算出这个进制下的十进制形式数字。如果 这个数字大于题目给出的那个进制数的十进制,那么说明我们的进制选大了,righ=mid-1,反之就是left=mid+1;

但是在转换成十进制时需要注意一个问题,那就是可能有时候会溢出,需要特判一下,如果溢出没那么说明肯定很大了,这个进制就太大了,需要right=mid-1;

整理思路大概这样,但是实现起来还是比较繁琐。

#include<cstdio>
#include<vector>
#include<cstring>
#include<string>
#include<stack>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
#include<iostream>
using namespace std;

typedef long long ll;
ll maps[256];
ll inf=(1ll<<43)-1;

void init(){
	for(char c='0';c<='9';c++){
		maps[c]=c-'0';
	}
	for(char c='a';c<='z';c++){
		maps[c]=c-'a'+10;
	}
}

ll convert_to_10(char martix[],ll radix,ll biggest_bound){
	ll ans=0;
	int len=strlen(martix);
	for(int i=0;i<len;i++){
		ans = ans*radix+maps[martix[i]];
		if(ans<0||ans>biggest_bound) return -1;
	}
	return ans;
}

int cmp(char martix[],ll radix,ll value){
	int len=strlen(martix);
	ll martix_num=convert_to_10(martix,radix,value);
	if(martix_num<0) return 1;
	if(value>martix_num) return -1;
	else if(value==martix_num) return 0;
	else return 1;
}


ll binarysearch(char martix[],ll left,ll right,ll value){
	ll mid;
	while(left<=right){
		mid = (left+right)/2;
		int flag=cmp(martix,mid,value);
		if(flag==0) return mid;
		else if(flag==-1) left=mid+1;
		else right=mid-1;
	}
	return -1;
}


ll findlargestdigit(char martix[]){
	long long ans=-1;
	int len=strlen(martix);
	for(int i=0;i<len;i++){
		if(maps[martix[i]]>ans) ans=martix[i];
	}
	return ans+1;
}

int main(){
	
	init();
	
	char str1[20],str2[20],temp[20];
	int tag,radix;
	scanf("%s %s %d %d",str1,str2,&tag,&radix);
	//不管怎么样,都让str1成为那个已知进制的数 
	if(tag==2){
		strcpy(temp,str1);
		strcpy(str1,str2);
		strcpy(str2,temp);
	}
	//将str1变成十进制
	ll str1_10 =  convert_to_10(str1,radix,inf);
	//找出str2中数位最大的那一个,加上1作为二分查找的下界 
	ll low_radix=findlargestdigit(str2);
	//上界我也有点迷糊 
	//上界的范围肯定要比下界高1,肯定要比十进制的自己要高1 
	ll high_radix=max(low_radix,str1_10)+1; 
	//在下界和上界之间找到正确的
	ll ans=binarysearch(str2,low_radix,high_radix,str1_10);
	if(ans==-1) printf("Impossible");
	else printf("%lld",ans);
	return 0;

}

3.Shopping in Mars

#include<cstdio>
#include<vector>
#include<cstring>
#include<string>
#include<stack>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
#include<iostream>
using namespace std;

int martix[100005];
int binary(int left,int right,int value){
	int mid;
	int lvalue=martix[left-1];
	while(left<=right){
		mid=(left+right)/2;
		if(martix[mid]-lvalue>value){
			right=mid-1;
		}else if(martix[mid]-lvalue<value){
			left=mid+1;
		}else{
			return mid;
		}
	}
	return -1;
}

int binary2(int left,int right,int value){
	int mid;
	int lvalue=martix[left-1];
	while(left<right){
		mid=(left+right)/2;
		if(martix[mid]-lvalue>value){
			right=mid;
		}else{
			left=mid+1;
		}
	}
	if(martix[right]-lvalue>value){
		return right;
	}else{
		return -1;
	}
}

int main(){
	
	int n,m;
	scanf("%d %d",&n,&m);
	int temp;
	for(int i=1;i<=n;i++){
		scanf("%d",&temp);
		martix[i]=martix[i-1]+temp;
	}
	int pos;
	bool flag=false;
	for(int i=1;i<=n;i++){
		pos=binary(i,n,m);
		if(pos!=-1){
			flag=true;
			printf("%d-%d\n",i,pos);
		}
	}
	int min_value=1000000000;
	if(!flag){
		for(int i=1;i<=n;i++){
			pos=binary2(i,n,m);
			if(pos!=-1){
			if(martix[pos]-martix[i-1]<min_value){
				min_value=martix[pos]-martix[i-1];
			}
		}
		}
		for(int i=1;i<=n;i++){
			pos=binary2(i,n,m);
			if(martix[pos]-martix[i-1]==min_value){
				printf("%d-%d\n",i,pos);
			}
		}
	}
	return 0;

}

4.Find Coins

这个做法有两个点无法通过

#include<cstdio>
#include<vector>
#include<cstring>
#include<string>
#include<stack>
#include<set>
#include<map>
#include<queue>
#include<algorithm>
#include<iostream>
using namespace std;

int martix[100005];
int n,m;
int getp(int l){
	int value=m-martix[l];
	int left=l,mid,right=n-1;
	while(left<=right){
		mid=(left+right)/2;
		if(martix[mid]>value){
			right=mid-1;
		}else if(martix[mid]<value){
			left=mid+1;
		}else return mid;
	}
	return -1;
}

int main(){
	
	scanf("%d %d",&n,&m);
	for(int i=0;i<n;i++){
		scanf("%d",&martix[i]);
	}
	sort(martix,martix+n);
	int pos;
	bool flag=false;
	for(int i=0;i<n;i++){
		pos=getp(i);
		if(pos!=-1&&pos!=i){
			flag=true;
			printf("%d %d",martix[i],martix[pos]);
			break;
		}
	}
	if(!flag) printf("No solution");
	

	return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值