蓝桥杯常用算法模板c++

蓝桥杯算法模板

又快到了一年一度的蓝桥杯省赛了,作为一个小萌新,自己复习一些蓝桥杯的算法并分享给大家。

判断闰年

bool isleaf(int x){
	return x%400==0||(x%4==0&&x%100!=0);
}

计数月,日或分钟等等

计算日的算法如下,小时分钟和秒就是在此基础上乘以相应的进制即可,月份就是在模板里面month++的时候顺便计数即可。

int syear,smonth,sday; //分别为结束年,月,日
int countday(int year,int month,int day){  //分别为开始的年月日
	int ans=0;
	int mon[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
	while(1){
		if(year==syear&&month==smonth&&day==sday){
			break;
		}
		day++;
		if(isleaf(year)&&month==2){
			if(day>mon[month]+1){
				month++;
				day=1;
			}
		}else{
			if(day>mon[month]){
				month++;
				day=1;
			}
		}
		if(month>12){
			month=1;
			year++;
		}
		ans++;
	}
	return ans;
}

筛选素数

筛选素数有许多种方法,首先是最简单的O(n^(3/2))的算法

bool isprime(int n){
	if(n==1)return false;
	for(int i=2;i*i<n;i++){
		if(n%i==0)return false;
	}
	return true;
}

埃氏筛法O(nloglogn)
埃氏筛法的基本思想:从2开始,将每个质数的倍数都标记成合数,以达到筛选素数的目的

bool visit[MAXN];
void prime(){
	memset(visit,false,sizeof(visit);  //初始化
	visit[0]=visit[1]=true;
	for(int i=2;i<=MAXN;i++){
		if(!visit[i]){
			for(int j=i*i;j<MAXN;j+=i){
				visit[j]=true;
			}
		}
	}
}
bool isprime(int n){
	return !visit[n];
}

但经过测试埃氏筛在超过100000之后效率不佳,于是就有了欧拉筛

欧拉筛

思想:在埃氏筛的基础之上,让每个合数只被最小质因子筛选一次,以达到不重复。

int prime[MAXN];
int visit[MAXN];
void olprime(){
	memset(visit,0,sizeof(visit));
	memset(prime,0,sizeof(prime));
	for(int i=2;i<=MAXN;i++){
		if(!visit[i]){
			prime[++prime[0]]=i;
		}
		for(int j=1;j<=prime[0]&&i*prime[j]<=MAXN;j++){
			visit[i*prime[j]]=1;
			if(i%prime[j]==0)break;
		}
	}
}

最大公约数gcd

int gcd(int a,int b){
	return b?gcd(b,a%b):a;
}

最小公倍数lcm

int lcm(int a,int b){
	return a*b/gcd(a,b);
}

多个数的gcd和lcm模板

int gcds(int a[],int n){
	int g=a[0];
	for(int i=1;i<n;i++){
		g=gcd(g,a[i]);
	}
	return g;
}
int lcms(int a[],int n){
	int l=a[0];
	for(int i=1;i<n;i++){
		l=lcm(a[i],l);
	}
	return l;
}

01背包问题

#include 
using namespace std;
int main(){
	int v[MAXN],w[MAXN],dp[MAXN];
	int m,n;//m为总背包大小,n为物品个数
	cin>>m>>n;
	for(int i=1;i<=n;i++){
		cin>>v[i]>>w[i];
	}
	for(int i=1;i<=n;i++){
		for(int j=m;j>=v[i];j--){
			dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
		}
	}
	cout<<dp[m];
}

完全背包

#include 
using namespace std;
int main(){
	int v[MAXN],w[MAXN],dp[MAXN];
	int m,n;//m为总背包大小,n为物品个数
	cin>>m>>n;
	for(int i=1;i<=n;i++){
		cin>>v[i]>>w[i];
	}
	for(int i=1;i<=n;i++){
		for(int j=v[i];j<=m;j++){
			dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
		}
	}
	cout<<dp[m];
}

两个背包问题的区别就是:01背包每个物品只能选一个,而完全背包问题可以多次选一个物品。

快速幂

#define long long ll
#define mod 1e9+7
ll quickpow(ll a,ll n){
	if(n==0||a==1)return 1;
	ll ans=1;
	while(n!=){
		if(n%2==1)ans=a*ans%mod;
		a=a*a%mod;
		n>>1;
	} 
	return ans;
}

求组合数C(n,m)模板

long long C(int n,int m){
	if(m==0)return1;
	long long ans=1;
	for(int i=n;i>n-m;i--)ans*=i;
	for(int i=m;i>1;i--)ans/=i;
	return ans;
}

这个算法的缺点在于如果会溢出,long long类型的数字到(83,41)就不能用了,所以我们借助大数

全排列

全排列C++有个叫next_permutation()的函数,这个函数的好处在于能够自动去重全排列,但要注意在操作前一定要将数组或者字符串排序,不然得到的结果不完整。

 vector<vector<int>> permuteUnique(vector<int>& nums) {
        vector<vector<int>> ret;
        sort(nums.begin(),nums.end());
        do{
            ret.emplace_back(nums);
        }while(next_permutation(nums.begin(),nums.end()));
        return ret;
 }

并查集

int n,m,cnt=0;
int f[10005];
int find(int x){
	if(f[x]==x)return x;
	return f[x]=find(f[x]);
}
void union(int x,int y){
	int a=find(x);
	int b=find(y);
	if(a!=b){
		f[a]=b;
		cnt++;
	}
}

你可能感兴趣的:(算法,algorithm)