算法笔记复现

区间贪心算法

//优先左最大
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=110;//const后面带int
struct inteval{
	double x;
	double y;
}s[maxn];
bool cmp(inteval a,inteval b){
	if(a.x!=b.x){
		return a.x>b.x;//先从左端点从大到小 
	}
	else{
		return a.y<b.y;//再从右端点从小到大 
	}	
}
int main(){
	int n;
	while(~scanf("%d",&n)){
		for(int i=0;i<n;i++){
			scanf("%lf %lf",&s[i].x,&s[i].y);//double输入	
		}
		sort(s,s+n,cmp);//检查引用algorithm
		int lx=s[0].x;
		int count=1;
		for(int i=1;i<n;i++){//从1开始
			if(s[i].y<lx){
				lx=s[i].x;
				count++;
			}
		}
		printf("%d\n",count);//不要忘了输出,输出不要忘了换行 
	} 
	return 0;
}
//优先右最小 
#include <cstdio>
#include <algorithm>
using namespace std;//不能漏 
struct inteval{
	double x;
	double y;
}s[110];
bool cmp(inteval a,inteval b){
	if(a.y!=b.y){
		return a.y<b.y; 
	} 
	else{
		return a.x>b.x;
	}
} 
int main(){
	int n=0;
	while(scanf("%d",&n)!=EOF){
		for(int i=0;i<n;i++){
			scanf("%lf %lf",&s[i].x,&s[i].y); //double输入
		}
		sort(s,s+n,cmp);
		int ly=s[0].y;
		int count=1;
		for(int i=1;i<n;i++){//从1开始
			if(s[i].x>ly){
				ly=s[i].y;
				count++;
			}
		}
		printf("%d\n",count);
	}
	return 0;
}

二分算法

#include <cstdio>
#include <algorithm>
using namespace std;
int binarySearch(int a[],int left,int right,int x){
	//a严格递增,非递归,二分查等于 
	//序列中是否存在满足某条件的元素 
	//二分区间[left,right],传入初值[0,n-1]; 
	int mid;
	while(left<=right){//这里是为了判断区间是否存在 
		mid=(left+right)/2;//mid=left+(right-left)/2;
		if(x<a[mid]){//严格递减:x>mid
			right=mid-1;//right!=mid
		}
		else if(x>a[mid]){//严格递减:x<mid
			left=mid-1;//left!=mid
		}
		else if(x==a[mid]){
			return mid;
		}
	}
	return -1;
} 
int h_equal(int a[],int left,int right,int x){//大等于的第一个数
//上界为n,即所有数都小于x返回n 
//二分区间[left,right],传入初值[0,n]; 
	while(left<right){
	//思路:假设存在,它该在的位置。因此是为了让循环一直执行 
		int mid=left+(right-left)/2;
		if(a[mid]>=x){
			right=mid;
		}
		else{
			left=mid+1;
		}
	}
	return left;//当right=left时停止,因此也可以return right,返回的都是夹出来的位置; 
}
int higher(int a[],int left,int right,int x){//大于x的第一个数 
//二分区间 [left,right],传入初值[0,n]; 
	while(left<right){
		int mid=left+(right-left)/2;
		if(a[mid]>x){
			right=mid;
		}
		else{
			left=mid+1;
		}
	}
	return right;//当right=left时停止,因此也可以return right,返回的都是夹出来的位置; 
} 
#define condition (1); 
int conditionSolve(int left,int right){//寻找某序列中第一个满足某条件的位置
//以“从左到右先不满足,然后满足”为例 
//二分区间[left,right],初值覆盖解的所有可能值
	while(left<right){//对闭区间夹结果来说,left==right则找到唯一位置 
	//左开右闭:while(left+1<right) 
		int mid=left+(right-left)/2;
		if(condition){
			right=mid;//条件成立往左找 
		}
		else{
			left=mid+1;//条件不成立往右找 
			//左开右闭:left=mid; 
		}
	}
	return left;//返回夹出来的位置 
	//左开右闭:return left+1; 
	//求最后一个满足条件condition的,等于求第一个满足条件!condition的 
} 
int main(){
	int n=0;
	int a[20];
	scanf("%d",&n);
	for(int i=0;i<20;i++){
		scanf("%d",&a[i]); 
	}
	sort(a,a+n);
	printf("%d\n",binarySearch(a,0,20,n));
	return 0; 
}  

木棒切割问题

#include <cstdio>
int solve(int k,int a[],int n){
	int l=0,x=k;
	while(l<a[0]){
		if(x>=k){
			l++;
			x=0;
			for(int i=0;i<n;i++){	
				x+=a[i]/l;
			}
		}
		else{
			return --l;
		}
	}
	return -1;
} 
int main(){
	int n=0,k=0;
	scanf("%d%d",&n,&k);
	int a[n]={0};
	for(int i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	printf("%d",solve(k,a,n));
	return 0;
}

快速幂算法

#include <cstdio>
typedef long long LL;
LL binaryPow(LL a,LL b){//递归写法 
	if(b==0){
		return 1;
	}
	if(b&1){
		return a*binaryPow(a,b-1); 
	} 
	else{
		int m=binaryPow(a,b/2);
		return m*m;
	}
} 
LL binaryPow2(LL a,LL b){//迭代写法 
	LL ans=1;
	while(b>0){
		if(b&1){
			ans*=a;
		}
		a*=a;
		b>>=1;//等同于b/=2; 
	}
	return ans;
}

two pointers

#include <cstdio>
//利用问题与序列本身的特性,使用两个下标对序列进行扫描来降低算法复杂度 
void twoPointers(int i,int j){
	while(i<j){
		if(i==j){
			i++;
			j--;
			printf("(%d,%d)",i,j);
		}
		else if(i<j){
			i++;
		}
		else{
			j--;
		}
	}
} 
int merge(int a[],int b[],int c[],int an,int bn){
	int index=0,i=0,j=0;
	while(i<an&&j<bn){
		if(a[i]<=b[j]){
			c[index++]=a[i++];
		}
		else{
			c[index++]=b[j++];
		}
	}
	while(i<an){
		c[index++]=a[i++];
	}
	while(j<bn){
		c[index++]=b[j++];
	} 
	return index;
}

归并排序递归算法

#include <cstdio>
#include <cstring> 
const int maxn=10010;
void merge(int a[],int l1,int r1,int l2,int r2){
	int i=l1,j=l2,index=0;
	int temp[maxn];
	memset(temp,0,sizeof(temp));
	while(i<=r1&&j<=r2){
		if(a[i]<=a[j]){
			temp[index++]=a[i++];
		}
		else{
			temp[index++]=a[j++];
		}
	}
	while(i<=r1){
		temp[index++]=a[i++];
	}
	while(j<=r2){
		temp[index++]=a[j++];
	}
	for(int i=0;i<index;i++){
		a[l1+i]=temp[i];
	}
} 
void mergeSort(int a[],int l,int r){
	if(l<r){
		int mid=(l+r)/2;
		mergeSort(a,l,mid);
		mergeSort(a,mid+1,r);
		merge(a,l,mid,mid+1,r);
	}
}
int main(){
	int n;
	int a[maxn];
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	mergeSort(a,0,n);
	for(int i=0;i<n;i++){
		printf("%d ",a[i]);
	}
}

归并排序非递归算法

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
void merge(int a[],int l1,int r1,int l2,int r2){
	int i=l1,j=l2,index=0;
	int temp[10010];
	memset(temp,0,sizeof(temp));
	while(i<=r1&&j<=r2){
		if(a[i]<=a[j]){
			temp[index++]=a[i++];
		}
		else{
			temp[index++]=a[j++];
		}
	}
	while(i<=r1){
		temp[index++]=a[i++];
	}
	while(j<=r2){
		temp[index++]=a[j++];
	}
	for(int i=0;i<index;i++){
		a[l1+i]=temp[i];
	}
} 
void mergeSort(int a[],int n){
	for(int step=2;step/2<=n+1;step*=2){
		for(int i=0;i<n;i+=step){
			int mid=i+step/2-1;
			if(mid+1<=n){
				merge(a,i,mid,mid+1,min(i+step-1,n-1));
			}
		}
	}
}
int main(){
	int n;
	int a[10010];
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		scanf("%d",&a[i]);
	}
	mergeSort(a,n);
	for(int i=0;i<n;i++){
		printf("%d ",a[i]);
	}
}

快速排序和随机选择

#include <cstdio>
#include <cstdlib>
#include <ctime>
int partition(int l,int r,int a[]){
	int p=(int)(rand()*1.0/RAND_MAX*50000+10000);
	int swap=a[l];
	a[l]=a[p];
	a[p]=swap;
	int temp=a[l];
	while(l<r){
		while(l<r&&a[r]>temp){
			a[l]=a[r];
		}
		while(l<r&&a[l]<=temp){
			a[r]=a[l];
		}
	}
	a[l]=temp;
	return l;
} 
void quickSort(int l,int r,int a[]){
	if(l<r){
		int pos=partition(l,r,a);
		quickSort(l,pos,a);
		quickSort(pos+1,r,a);
	}	 
} 
int randSelect(int a[],int l,int r,int k){
	if(l==r){
		return a[l];
	}
	int p=partition(l,r,a);
	int m=p-l+1;//p是第m大的数 
	if(m==k){
		return a[p];
	}
	else if(m<k){
		randSelect(a,p+1,r,k-m);
	}
	else if(m>k){
		randSelect(a,l,p-1,k);
	}
	
} 

分数的表示、化简、加减乘除

#include <cstdio>
#include <algorithm> 
//一般情况下分子分母用long long型存储 
struct Fraction{
	int up;//不能直接int up=0;来初始化 
	int down;
}f1; 
int gcd(int a,int b){
	if(a<b){
		int temp=a;
		a=b;
		b=temp;
	}
	if(b==0){
		return a;
	}
	else{
		return gcd(b,a%b);
	}
}
Fraction fraReduction(Fraction f){//需要调用的函数要写在前面 
	if(f.down<0){
		f.down=-f.down;
		f.up=-f.up;
	}
	if(f.up==0){//正常运算分母不可能先为0,必是当分子为零时改分母 
		f.down=1;
	}
	else{
		f.up/=gcd(abs(f.up),abs(f.down));//要加abs 
		f.down/=gcd(abs(f.up),abs(f.down));		
	}
	return f;
}
Fraction fraAdd(Fraction f1,Fraction f2){
	Fraction f;
	f.up=f1.up*f2.down+f2.up*f1.down;
	f.down=f1.down*f2.down;
	return fraReduction(f);
}
Fraction fraMinu(Fraction f1,Fraction f2){
	Fraction f;
	f.up=f1.up*f2.down-f2.up*f1.down;
	f.down=f1.down*f2.down;
	return fraReduction(f);
}
Fraction fraMulti(Fraction f1,Fraction f2){
	Fraction f;
	f.up=f1.up*f2.up;
	f.down=f1.down*f2.down;
	return fraReduction(f);
}
Fraction fraDivide(Fraction f1,Fraction f2){
	if(f2.up==0){
		printf("Error.");
		return f2;
	}
	else{
		Fraction f;
		f.up=f1.up*f2.down;
		f.down=f1.down*f2.up;
		return fraReduction(f);
	}
}
void fraResult(Fraction f){
	//考虑:化简,整数,假分数 
	f=fraReduction(f);
	if(f.down==1){
		printf("%d",f.up); 
	}
	else{
		if(f.down<f.up){
			printf("%d %d/%d",f.up/f.down,f.up%f.down,f.down);
		}
		else{
			printf("%d/%d",f.up,f.down);
		}
	}
}
int main(){
	scanf("%d %d",&f1.up,&f1.down);
	f1=fraReduction(f1);
	printf("%d/%d\n",f1.up,f1.down);
} 

简单素数表生成法

#include <cstdio>
#include <cmath>
bool isPrime(int n){
	if(n<=1){
		return false;
	}
	int sqr=(int)sqrt(n);
	for(int i=2;i<=sqr;i++){//从2开始 
		if(n%i==0){
			return false;
		}
	}
	return true;
} 
int prime[100010]={0};
int priNum=0;
int Find_prime(int n){
	for(int i=2;i<=n;i++){
		if(isPrime(i)){
		prime[priNum++]=i;
		}
	}
}
int main(){
	int n;
	scanf("%d",&n);
	Find_prime(n);
	for(int i=0;i<priNum;i++){
		printf("%d ",prime[i]);
	} 
	return 0;
}

欧拉筛素数

#include <cstdio> 
#include <cmath>
const int maxn=10010;
bool isnotPrime[maxn]={false};//不能初始化为true,否则其它还会是false 
int prime[maxn]={0};
int priNum=0;
int olaPrime(int n){	
	for(int i=2;i<=n;i++){
		if(isnotPrime[i]==false){
			prime[priNum++]=i;
			for(int j=i+i;j<=maxn;j+=i){
				isnotPrime[j]=true;
			}
		}
	}
}
int main(){//不能漏 
	int n;
	scanf("%d",&n);
	olaPrime(n);//不能漏 
	if(n>1){
		for(int i=2;i<=n;i++){
			if(isnotPrime[i]==false){
				printf("%d ",i);	
			}		
		}		
	}
	return 0;
}

大数加减乘除

#include <cstdio>
#include <cstring>
struct bign{
	int d[1000];
	int len;
	bign(){
		memset(d,0,sizeof(d));//只能用memset赋值 
		len=0;
	}
};//分号不能少 
bign bchange(char c[]){
	bign a;
	a.len=strlen(c);
	for(int i=0;i<a.len;i++){
		a.d[i]=c[a.len-i-1]-'0';
	}
	return a;
}
int compare(bign a,bign b){
	if(a.len>b.len)return 1;
	else if(a.len<b.len)return -1;
	else{
		for(int i=0;i<a.len;i++){
			if(a.d[i]>b.d[i])return 1;
			else if(a.d[i]<b.d[i])return -1;//不能漏 
		}
	}
	return 0;
}
bign badd(bign a,bign b){
	int carry=0;//进位 
	bign c;
	for(int i=0;i<a.len||i<b.len;i++){//不能仅是i<a.len 
		c.d[c.len++]=(a.d[i]+b.d[i]+carry)%10;//直接写上c.len++ 
		carry= (a.d[i]+b.d[i]+carry)/10;
	}
	if(carry!=0){
		c.d[c.len++]=carry;
	}
	return c;//不能漏 
} 
bign bsub(bign a,bign b){
	bign c;
	for(int i=0;i<a.len||i<b.len;i++){
		if(a.d[i]<b.d[i]){
			a.d[i+1]--;
			a.d[i]+=10;
		}
		c.d[c.len++]=a.d[i]-b.d[i];
	}
	while(c.d[c.len-1]==0&&c.len>=2){
		c.len--;
	}
	return c;
}
bign bmulti(bign a,int b){
	int carry=0;
	bign c;
	for(int i=0;i<a.len;i++){
		int temp=a.d[i]*b+carry;
		c.d[c.len++]=temp%10;//不是c.d[i] 
		carry=temp/10;
	}
	while(carry!=0){
		c.d[c.len++]=carry%10;//carry和temp不能混 
		carry/=10; 
	}
	return c;//不能漏 
}
bign bdivide(bign a,int b,int& r){
	bign c;
	c.len=a.len;//c也是从高到低 
	for(int i=a.len-1;i>=0;i--){
		r=r*10+a.d[i];
		c.d[i]=r/b;
		r%=b;//不是r/=10 
	}	
	while(c.len>=2&&c.d[c.len-1]==0){
		c.len--;
	}
	return c;
}
int main(){
	char n1[1000]={' '};
	char n2[1000]={' '};
	int n3=0;
	while(scanf("%s %s %d",n1,n2,&n3)!=EOF){
		int r=0;
		bign b1=bchange(n1);
		bign b2=bchange(n2);
		bign c=badd(b1,b2);//不能直接用n1,n2加
		bign d;
		if(compare(b1,b2)==-1){
			d=bsub(b2,b1);
		}
		else{
			d=bsub(b1,b2);//只允许b1>=b2
		}
		bign e=bmulti(b1,n3);
		bign f=bdivide(b1,n3,r);//引用传参r 
		printf("%s+%s=",n1,n2);
		for(int i=0;i<c.len;i++){//e.len什么的灵活调整 
			printf("%d",c.d[c.len-i-1]);	
		}
		printf("\n%s-%s=",n1,n2);
		if(compare(b1,b2)==-1){printf("-");}
		for(int i=0;i<d.len;i++){
			printf("%d",d.d[d.len-1-i]);
		}
		printf("\n%s*%d=",n1,n3);
		for(int i=0;i<e.len;i++){
			printf("%d",e.d[e.len-1-i]);
		}
		printf("\n%s/%d=",n1,n3);
		for(int i=0;i<f.len;i++){
			printf("%d",f.d[f.len-1-i]);
		}
		printf("...%d",r);
		printf("\n");
	}
	return 0;
} 

公约数公倍数

#include <cstdio>
int gcd(int a,int b){
	if(b==0){
		return a;
	}
	else{
		return gcd(b,a%b);
	}
}
int lcm(int a,int b){
	return a/(gcd(a,b))*b;
}
int main(){
	int a=0,b=0;
	while(scanf("%d %d",&a,&b)){
		printf("gcd(a,b)=%d\nlcm(a,b)=%d\n",gcd(a,b),lcm(a,b));
	}
	return 0;
}

欧几里得算法简单拓展

//a*x1+b*y1=gcd(a,b)
//b*x2+(a%b)*y2=gcd(a,b);
//a*x1+b*y1=b*x2+(a%b)*y2;(整除)
//a%b=a-(a/b)*b;
//a*x1+b*y1=b*x2+(a-(a/b)*b)*y2(整除)
//a*x1+b*y1=b*x2+a*y2-(a/b)*b*y2;
//a*x1+b*y1=a*y2+b*(x2-(a/b)*y2);
//x1=y2;
//y1=(x2-(a/b)*y2); 
int exGod(int a,int b,int &x,int &y){
	if(b==0){
		x=1;y=0;
		return a;
	}
	int g=exGod(b,a%b,x,y);
	int temp=x;
	x=y;//x1=y2;
	y=temp-a/b*y;//y1=(x2-(a/b)*y2);
	return g; 
}
int main(){
	int a=0,b=0,x=0,y=0;
	while(~scanf("%d %d",&a,&b)){
		printf(exGod(x,y));
	}
}

n!问题

#include <cstdio>
int cal1(int n,int p){//n!中质因子p的个数 
	int ans=0;
	while(n){
		ans+=n/p;
		n/=p;
	}
	return ans;
}
int cal2(int n,int p){
	if(n<p)return 0;
	else{
		return n/p+cal(n/p,p);//(n/p)!中质因子p的个数 
	}
}
int main(){
	int a=0,b=0;
	while(~scanf("%d %d",&a,&b)){
		printf("%d\n",cal(a,b));
	}
	return 0;
}

组合数计算

#include <cstdio>
long long c(long long n,long long m){
	long long ans=1;
	for(int i=1;i<=m;i++){
		ans=ans*(n-m+i)/i;
    }
	return ans; 
} 
int main(){
	long long n=0,m=0;
	scanf("%lld %lld",&n,&m);
	printf("%lld",c(n,m)); 
}
发布了28 篇原创文章 · 获赞 0 · 访问量 839

猜你喜欢

转载自blog.csdn.net/weixin_44211856/article/details/104550618