蓝桥杯刷题笔记

0 杂

//ASCII码
数字-48
A=65
a=97

//字符串分割
//从下标0开始取n-1个字符
str = str.substr(0,n-1)

//二维vector的添加数据以及遍历
vector<vector<int>> v;
for(int i = 0;i < 2;i++)
{
		vector<int> tmp;
		for(int j = 0;j < 2;j++)
		{
			tmp.push_back(j);
		}
		v.push_back(tmp);
}
for(int i = 0;i < v.size(); i++)
{
		for(int j = 0;j < v[i].size();j++)
		{
			cout<<v[i][j]<<" ";
		}
		cout<<endl;
}


//cin加速
#include < iostream>
int main() 
{
    std::ios::sync_with_stdio(false);//消除输入输出缓存
    std::cin.tie(0);//解除cin与cout的绑定,加快速率。
}

1 手写组合

//dfs版
#include<bits/stdc++.h>
using namespace std;
int a[]={1,2,3,4,5,6,7,8,9,10};
int vis[10];
void dfs(int k) {  
    if (k == 3) {
        for(int i=0;i<3;i++)
            if(vis[i])  cout<<a[i];
        cout<<"-";
    }
    else {
        vis[k] = 0;          //不选中第k个数
        dfs(k + 1);          //继续搜下一个数
        vis[k] = 1;          //选这个数
        dfs(k + 1);          //继续搜下一个数
    }
}
int main() {
    dfs(0); //从第一个数开始
    return 0;
}

2 手写全排列

#include<algorithm>
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
int a[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13};
int b[20];
bool marked[20];
//手写全排列 
void dfs(int s,int t)
{
    //若要打印n个数中任意m个数的全排列,改为s==m
	if(s == t)
	{
        //若要打印n个数中任意m个数的全排列,改为i<m
		for(int i = 0;i < t;i++)
		{
			cout<<b[i]<<" ";
		}
		cout<<"\n";
		return;
	}
	for(int i = 0;i < t;i++)
	{
		if(!marked[i])
		{
			marked[i] = true;
            //注意是b[s]
			b[s] = a[i];
			dfs(s+1,t);
			marked[i] = false;
		}
	}
}
int main(void)
{
	int n;
	cin>>n;
	dfs(0,n);
	return 0;
}

//STL全排列函数
C++ STL:求“下一个”排列组合的函数next_permutation()。
返回值:如果没有下一个排列组合,返回false,否则返回true。每执行next_permutation()一次,会把新的排列放到原来的空间里。
注意,它排列的范围是[first, last),包括first,不包括last。
next_permutation()从当前的全排列开始,逐个输出更大的全排列,而不是输出所有的全排列。

3 kmp

1. 初始化next数组,令 j = next[0] = -1;
2. 让i在1 ~ len - 1范围遍历,对每个i执行3、4,以求解next[i];
3. 不断让j = next[j],直到j回退为-1,或是s[i] == s[j+1]成立。
4. 如果s[i] == s[j+1],则next[i] = j+1,否则next[i] = j。
    
    
void getNext(void getNext(string s,int len)
{
	int j = -1;
	next[0] = -1; //初始化j = next[0] = -1
	for(int i = 0; i < len; i++)	//求解next[1] ~ next[len - 1]
	{
		while(j != -1 && s[i] != s[j + 1])
		{
			j = next[j]; //反复令j = next[j]
		} // 直到j回退到-1,或是s[i] = s[j + 1]
		if(s[i] == s[j + 1]) //如果s[i] == s[j+1]
		{
			j = j+1;	//则next[i] = j + 1,先令j指向这个位置
		}
		next[i] = j;
	}
}
bool kmp(string text,string pattern)
{
	int n = text.length();
	int m = pattern.length();
	getNext(pattern,m);	//计算pattern的next数组 
	int j = -1;	//初始化j为-1,表示当前还没有任意一位被匹配 
	for(int i = 0; i < n; i++) //试图匹配text[i] 
	{
		while(j != -1 && text[i] != pattern[j + 1])
		{
			j = next[j];	//不断回退,直到j回到-1或text[i] == pattern[j+1] 
		}
		if(text[i] == pattern[j + 1])
		{
			j++;	//text[i]与pattern[j+1]匹配成功,令j加1 
		}
		if(j == m - 1)	//pattern完全匹配,说明pattern是text的子串 
		{
			return true;
		}
	}
	return false;
})

4 并查集

int c[maxn], N;
inline void init()
{
    for(int i=0; i<=N; i++){
        c[i] = i;
    }
}
int Findset(int x)
{
    int root = x;
    while(c[root] != root)
        root = c[root];

    int idx;
    while(c[x] != root){ /// 路径压缩
        idx = c[x];
        c[x] = root;
        x = idx;
    }
    return root;
}
inline void Join(int a, int b)
{
    int A = Findset(a);
    int B = Findset(b);
    if(A != B) c[A] = B;
}

5 快排

void quickSort(int left,int right)
{
	if(left > right)
		return;
	int i = left;
	int j = right;
	int tmp = num[i];
	while(i < j)
	{
		while(num[j] >= tmp && i != j)
			j--;
		while(num[i] <= tmp && i != j)
			i++;
		if(i < j)
			swap(num[i],num[j]);
	}
	num[left] = num[i];
	num[i] = tmp;
    //注意是i-1,不是什么mid-1
	quickSort(left,i - 1);
	quickSort(i+1,right);
	return;
}

6 归并

#include <iostream>
using namespace std;
void Merge(int a[],int s,int m, int e,int tmp[])
{
	//将数组a的局部a[s,m]和a[m+1,e]合并到tmp,并保证tmp有序,然后再拷贝回a[s,m]
//归并操作时间复杂度:O(e-m+1),即O(n)
	int pb = 0;
	int p1 = s,p2 = m+1;
	while( p1 <= m && p2 <= e)
	{
		if( a[p1] < a[p2])
			tmp[pb++] = a[p1++];
		else
			tmp[pb++] = a[p2++];
	}
	while( p1 <= m)
		tmp[pb++] = a[p1++];
	while( p2 <= e)
		tmp[pb++] = a[p2++];
    //0 ~ e-s+1
	for(int i = 0; i < e-s+1; ++i)
		a[s+i] = tmp[i];
}
void MergeSort(int a[],int s,int e,int tmp[])
{
	if( s < e)
	{
		int m = s + (e-s)/2;
        //注意是m,不是m-1
		MergeSort(a,s,m,tmp);
		MergeSort(a,m+1,e,tmp);
		Merge(a,s,m,e,tmp);
	}
}
int a[10] = { 13,27,19,2,8,12,2,8,30,89};
int b[10];
int main()
{
	int size = sizeof(a)/sizeof(int);
	MergeSort(a,0,size-1,b);
	for(int i = 0; i < size; ++i)
		cout << a[i] << ",";
	cout << endl;
	return 0;
}

7 重载运算符

//定义在结构体内部
bool operator <(const person &t)const{
    return t.a > a;
}
sort(p+1, p+1+n*2);


struct node{
	int id;
	//优先队列排序用 
	ll dis_n;
	node(int a,ll b){
		id = a;
		dis_n = b;
	}
	bool operator <(const node &a)const{
		return dis_n>a.dis_n;
	}
};

8 二分

int BinarySearch(int a[],int size,int p)
{
	int L = 0; //查找区间的左端点
	int R = size - 1; //查找区间的右端点
    //左闭右闭就是 <=
	while( L <= R)   //如果查找区间不为空就继续查找
	{
		int mid = L+(R-L)/2; //取查找区间正中元素的下标
		if( p == a[mid] )
			return mid;
		else if( p > a[mid])
			L = mid + 1; //设置新的查找区间的左端点
		else
			R = mid - 1; //设置新的查找区间的右端点
	}
	return -1;
} //复杂度O(log(n))


//后继
#include<bits/stdc++.h>
using namespace std;
int a[1000];
int bin_search(int *a, int n, int x){     //a[0]~a[n-1]是单调递增的
    int left = 0, right = n;        //注意:不是 n-1,此时是左闭右开的[0,n)
    while (left < right) {
        int mid = left + (right-left)/2;  //int mid=(left+right)>>1;
        if (a[mid] >= x)  right = mid;
        else    left = mid + 1;
    }                                     //终止于left = right
   return left;
}
int main(){
    int n = 100;
    for(int i=0;i<n;i++) a[i]=2*i+2;      //赋值,数字2~200,偶数
    int test = 55;                        //找55或55的后继
    int pos = bin_search(a,n,test);
    cout<<"test="<<a[pos];              
}


//前驱
#include<bits/stdc++.h>
using namespace std;
int a[1000];
int bin_search2(int *a, int n, int x){    //a[0]~a[n-1]是单调递增的
    int left = 0, right = n;
    while (left < right) {
        int mid = left + (right-left + 1)/2 ;
        if (a[mid] <= x)  left = mid;
        else  right = mid - 1;
    }                                     //终止于left = right
   return left;
}
int main(){
    int n = 100;
    for(int i=0;i<n;i++) a[i]=2*i+2;     //赋值,数字2~200,偶数
    int test = 55;                       //找55或55的前驱
    int pos = bin_search2(a,n,test);
    cout<<"test="<<a[pos];
}

//精度控制
for(int j = 0; j < 100; j++) //控制精度在10^(-2)
{
	double mid = left + (right - left)/2;
	if(getY(mid)*getY(right) <= 0)
		left = mid;
	else
		right = mid;
}
printf("%.2lf ",right);

//精度控制
const double eps = 1e-3;
while(right - left > eps)
{
	double mid = left + (right - left)/2;
	if(mid*mid*mid < num)
		left = mid;
	else
		right = mid;
}

9 GCD

//辗转相除法
//最大公因数普通算法
int gcd(int m,int n)
{    
    int t,r;    
    if (m<n)//为了确保是大数除小数    
    {        
        t=m;        
        m=n;       
        n=t;    
    }    
 
    while((m%n)!=0)//辗转相除    
    {        
        r=m%n;        
        m=n;        
        n=r;    
    }   
 
    return n;
}

'''
考察gcd性质,根据更相减损术可以知道一个等式:gcd(a,b)=gcd(a,b-a)  当然这里的前提是a<=b;
所以gcd(a+k,b+k)=gcd(a+k,b-a)  这里的a和b都是已知的
我们可以设c=b-a    即c是已知的  所以想要使得a+k与c的最大公因子尽可能地大  因为最大最大能到达c
显然这个式子的最大gcd一定为 c ,我们只需要计算出a 最少需要增加多少可以成为 c 的倍数,这个增量即是答案k
'''
    
#include<iostream>
#include<cmath>
using namespace std;
typedef long long LL;

int main(){
    LL a,b;
    cin>>a>>b;
    LL m = abs(a-b);
    LL d = a%m;
    LL k;
    k = (d==0 ? 0 : m-d);
    cout<<k<<endl;
}

10 质因数个数

typedef long long ll;
ll n;
ll drivePrime(ll num)
{
	ll i,cnt = 0,k = num;
	for(i = 2; i * i <= k; i++)
	{
		if(num % i == 0)
		{
			while(num%i == 0)
				num /= i;
			cnt++; 
		 } 
	}
	if(num > 1)
		cnt++;
	return cnt;
}

11 素数

//线性筛
int su[2050],cnt;
bool isPrime[2050];
void prime()
{
    cnt = 0;
    memset(isPrime,true,sizeof(isPrime));
    isPrime[0] = isPrime[1] = false; //0,1不是素数
    //i从2到maxn
    for(int i = 2;i <= maxn;i++) // <=
    {
        if(isPrime[i]) //保存素数
            su[cnt++] = i;
        for(int j = 0;j < cnt && su[j]*i <= 2020;++j) // <=
            //false
            isPrime[su[j]*i] = false;
    }
}

12 DFS、BFS

迷宫

#include<stdio.h>
#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
struct node{
	int x;
	int y;
	string path = "";
};
char graph[31][51];
int dir[4][2] = {{1,0},{0,-1},{0,1},{-1,0}};
bool marked[31][51];
char k[4]={'D','L','R','U'};
queue<node> qu;
void bfs(int x,int y)
{
	marked[x][y] = true;
	node n;
	n.x = x;
	n.y = y;
	qu.push(n);
	
	while(!qu.empty())
	{
		node cur = qu.front();
		
		qu.pop();
		for(int i = 0;i < 4;i++)
		{
			
			node newn;
			newn.x = cur.x + dir[i][0];
			newn.y = cur.y + dir[i][1];
			
			//cout<<dir[i][0]<<endl;
			if(newn.x == 29 && newn.y == 49)
			{
				newn.path = cur.path + k[i];
				cout<<newn.path;
				return;
			}
			//cout<<graph[1][0]<<endl;
			if(newn.x >= 0 && newn.x < 30 && newn.y >=0 && newn.y < 50  && graph[newn.x][newn.y] == '0' && !marked[newn.x][newn.y])
			{
				//cout<<i<<":"<<newn.x<<endl;
				marked[newn.x][newn.y] = true;
				
				newn.path =cur.path + k[i];
				
				qu.push(newn);
			}
		}
	}
}
int main(void)
{
	for(int i = 0;i < 30;i++)
	{
		for(int j = 0;j < 50;j++)
		{
			scanf("%c",&graph[i][j]);
		}
		getchar();
	}
	bfs(0,0);
	return 0;
}

跳蚱蜢

#include<string>
#include<queue>
#include<algorithm>
#include<map>
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
struct node
{
	node() {}
	node(string ss,int tt)
	{
		s = ss,t = tt;
	}
	string s;
	int t;
};
queue<node> q;
map<string,bool> mp;
void bfs()
{
	while(!q.empty())
	{
		node now = q.front();
		q.pop();
		string s = now.s;
		int step = now.t;
		if(s == "087654321")
		{
			cout<<step<<"\n";
			break;
		}
		int idx;
		for(int i = 0; i < 10; i++)
		{
			if(s[i] == '0')
			{
				idx = i;
				break;
			}
		}
		for(int j = idx - 2; j <= idx + 2; j++)
		{
			if(j == idx)
				continue;
			int cur = (j+9)%9;
			string news = s;
			char tmp = news[idx];
			news[idx] = news[cur];
			news[cur] = tmp;
			if(!mp[news])
			{
				mp[news] = true;
				q.push(node(news,step+1));
			}
		}
	}
}
int main(void)
{
	string s = "012345678";
	q.push(node(s,0));
	mp[s] = true;
	bfs();
	return 0;
}

七段码

#include<string>
#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
int mp[10][10];
map<string,bool> m;
int cnt;
bool marked[10];
int c[10];
void init()
{
	//并查集初始化
	for(int i = 0;i < 7;i++)
		c[i] = i;
}
int findSet(int x)
{
	int root = x;
	while(c[root] != root)
		root = c[root];
	
	int idx;
	while(c[x] != root)
	{
		idx = c[x];
		c[x] = root;
		x = idx;
	}
	return root;
}
void join(int a,int b)
{
	int A = findSet(a);
	int B = findSet(b);
	if(A != B)
	{
		c[A] = B;
	}
}
bool check()
{
		init();
		for(int i = 0;i < 7;i++)
		{
			for(int j = 0;j < 7;j++)
			{
				if(mp[i][j] == 1 && marked[i] && marked[j])
				{
					join(i,j);
				}
			}
		}
		int ct = 0;
		for(int i = 0;i < 7;i++)
		{
			if(marked[i] && c[i] == i)
				ct++;
		}
		if(ct == 1)
			return true;
		return false;
}
void dfs(int s)
{
	if(s == 7)
	{
		 if(check())
		 	cnt++;
	}
	else
	{
		marked[s] = true;
		dfs(s+1);
		marked[s] = false;
		dfs(s+1);
	}
} 
int main(void)
{
	for(int i = 0;i < 10;i++)
	{
		int u,v;
		cin>>u>>v;
		mp[u][v] = mp[v][u] = 1;
	}
	dfs(0);
	cout<<cnt;
	return 0;
 }

全球变暖(DFS判断连通块个数)

#include<stdio.h>
#include<string>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
bool marked[1010][1010];
char graph[1010][1010];
//上,左,下,右
int dir[4][2] = {{-1,0},{0,-1},{1,0},{0,1}};
int n;
//每块陆地有多少个小格
int ct1;
//统计与海水相邻的格子数,如果ct2!=ct1,则说明有格子不临海
int ct2;
void dfs(int x,int y)
{
    if(graph[x][y] == '.')
        return ;
//    cout<<"x: "<<x<<" y: "<<y<<endl;
    marked[x][y] = true;
    ct1++;
    bool flag = false;
    for(int i = 0; i < 4; i++)
    {
        int x1 = x + dir[i][0];
        int y1 = y + dir[i][1];
        if(x1 < n && x1 >= 0 && y1 < n && y1 >= 0 && !marked[x1][y1])
        {
            if(graph[x1][y1] == '.' && !flag)
            {
            //    cout<<"x: "<<x<<" y: "<<y<<" x1: "<<x1<<" y1: "<<y1<<endl;
                ct2++;
                flag = true;
            }
            dfs(x1,y1);
        }
    }
    
}
int main(void)
{
    cin>>n;
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            cin>>graph[i][j];
        }
    }
    int cnt = 0;
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            if(!marked[i][j] && graph[i][j] == '#')
            {
                ct1 = 0;
                ct2 = 0;
                dfs(i,j);
                if(ct1 == ct2 && ct2 != 0)
                    cnt++;
            //    cout<<"ct1: "<<ct1<<" ct2: "<<ct2<<" cnt: "<<cnt<<endl;
            }
        }
    }
    cout<<cnt;
    return 0;
}

12 最短路

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<map>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
const int total = 1e4+10;
const int inf = 0x3f3f3f3f;
struct node{
	int id;
	//优先队列排序用 
	ll dis_n;
	node(int a,ll b){
		id = a;
		dis_n = b;
	}
	bool operator <(const node &a)const{
		return dis_n>a.dis_n;
	}
};
struct edge{
	int u,v,w;
	edge(int a,int b,int c){
		u = a;
		v = b;
		w = c;
	}
};
vector<edge> e[total];
//注意map和set判重时间复杂度为log,如果能开大数组判重优先开数组
map<int,bool> mp;
priority_queue<node> q;
long long dis[2030];
int lms(int a,int b)
{
	return a/__gcd(a,b) * b;
}
void dij()
{
	int s = 1;
	dis[s] = 0;
	q.push(node(1,0));
	while(!q.empty())
	{
		node now = q.top();
		q.pop();
		if(mp[now.id])
			continue;
		mp[now.id] = true;
		for(int i = 0;i < e[now.id].size();i++)
		{
			int v = e[now.id][i].v;
			int w = e[now.id][i].w;
			if(!mp[v] && dis[now.id] + w < dis[v])
			{
				dis[v] = dis[now.id] + w;
				q.push(node(v,dis[v]));
			}
		}
	}
}
int main(void)
{
	int n;
	cin>>n;
    //注意初始化dis数组为inf
	memset(dis,inf,sizeof(dis));
	for(int i = 1;i <= n;i++)
	{
		for(int j = i+1;j <= n;j++)
		{
			if(j - i <= 21)
			{
				int w = lms(j,i);
				e[i].push_back(edge(i,j,w));
				e[j].push_back(edge(j,i,w));
			}
		}
	}
	dij();
	cout<<dis[n]; 
	return 0;
} 

13 快速幂

#include<iostream>
#include<stdio.h>
#include<string>
using namespace std;
typedef long long ll;
ll fastPow(ll a, ll n,ll mod)
{
	ll ans = 1;
	//重要,防止下面的ans*a越界
	a %= mod; 
	while(n)
	{
		if(n&1)
		{
			ans = (ans * a) % mod;
		}
		a = a*a%mod;
		n>>=1;
	}
	return ans;
}
int main(void)
{
	ll b,p,k;
	cin>>b>>p>>k;
	cout<<fastPow(b,p,k);
	return 0;
}
posted @ 2023-05-02 09:56  曹剑雨  阅读(14)  评论(0编辑  收藏  举报