随手小札

结构体

今天我们来总结一下struct和typedef struct在C语言和C++里的不同
随手小札_第1张图片
随手小札_第2张图片

next_permutation函数

1-4的全排列

#include
using namespace std;
int main(){
	int a[4]={1,2,3,4};
	sort(a,a+4);
	do{
		for(int i=0;i<4;i++){
			cout<<a[i]<<" ";
		}
		cout<<endl;
	}while(next_permutation(a,a+4));
	return 0;
}

字符串按照字典序全排列

#include
using namespace std;
int main(){
	string str;
	cin>>str;
	sort(str.begin(),str.end());
	do{
		cout<<str<<endl;
	}while(next_permutation(str.begin(),str.end()));
	return 0;
}

长度

  1. sizeof运算符指出的是整个数组的长度
  2. strlen返回的是存储在数组中的字符串的长度,而非数组本身长度
  3. strlen只计算可见字符,而不会包含结束字符‘\0’
  4. 存储字符串到字符数组中要求数组长度至少为字符串长度strlen+1
  5. 字符串以‘\0’为结束标志

判断

#include 

在这个头文件里面
判断是否为十进制数字isdigit
如果 c 是一个数字,则该函数返回非零值,否则返回 0。
判断是否为字母isalpha
如果 c 是一个字母,则该函数返回非零值,否则返回 0。
判断是否为数字或者字母isalnum
如果 c 是一个数字或一个字母,则该函数返回非零值,否则返回 0

不可修改

const int * a;
const修饰的是整型数 int,而不是指针,即a是一个指向常整型数的指针。近一步的理解为:整型数 a是不可以被重新赋值的,而指针却是可以修改的,可以重新指向另外一个内存地址;
int * const a;
const修饰的是指针a,而不是整型数
a,*a为变量而不是一个常量。即a是指向一个可以修改的整型数的常指针。进一步的理解为:指针指向的整型数是可以被修改的,但是指针不可以被修改。
int const * a const;
a是指向一个常整型数的常指针,即指针不可修改,指针指向的整型数也是不可以被修改的。

异或

判断奇数偶数
一个数的二进制里面有几个1
a^a=0;
a^b=不为0;
其他的
1&1=1;
1&2=0;

#include
using namespace std;
int main(){
	int n,i,a[20],m=-1;
	scanf("%d",&n);
	while(n){
        i=n%2;
        a[++m]=i;
        n=n/2;
    }
    for(int j=m;j>=0;j--)
        printf("%d",a[j]);
    printf("\n");
    int ans;
    for(int i=0;i<=m;i++){
    	if(1^a[i]==0){
    		ans++;
		}
	}
	printf("%d ",ans);
//	cout << bitset<32>(n) << endl;
} 

蓝桥杯

投机取巧的学了一丢丢excel里面计算日期的小tips

1-2020所有的2

#include
int main(){
	int ans=0;
	for(int i=1;i<=2020;i++){
		int m=i;
		while(m){
			if(m%10==2){
				ans++;
			}
			m/=10;
		}
	}
	printf("%d",ans);
	return 0;
} 

公约数为1的所有对数

#include
#include
#include
#include
#include

using namespace std;
int main(){
	int ans=0;
	for(int i=1;i<=2020;i++){
		for(int j=1;j<=2020;j++){
			if(__gcd(i,j)==1){
				ans++;
			}
		}
		
	}
	printf("%d",ans);
	return 0;
} 

蛇形填数

#include 
int a[100][100];
int cnt=1;
int main(){
	int i;
	int x,y;
    for(i = 1 ; i <= 40; i++){
        if(i % 2==1 ){
            for(x = i, y = 1; x >= 1 && y <= i; x--, y++)
                a[x][y] = cnt++;
        }
        else{
            for(int x = 1, y = i; x <= i && y >= 1; x++, y--)
                a[x][y] = cnt++;
        }
    }
    printf("%d\n", a[20][20]);
	return 0;
}

跑步

#include
int main(){
	int a[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
	int w=6;
	int sum=0;
	for(int y=2000;y<=2020;y++){
		if((y%400==0)||(y%4==0&&y%100!=0)){
			a[2]=29;
		}else{
			a[2]=28;
		}
		for(int m=1;m<=12;m++){
			for(int d=1;d<=a[m];d++){
				if(d==1||w==1){
					sum+=2;
				}else{
					sum+=1;
				}
				w=(w+1)%7;
				if(y==2020&&m==10&&d==1){
					printf("%d",sum);
					return 0;
				}
			}
		}
	}
	
}

成绩统计:

#include
#include
#include
using namespace std;

int main(){
	int n;
	scanf("%d",&n);
	int a[1005];
	memset(a,0,sizeof(a));
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	int jige=0;
	int youxiu=0;
	for(int i=1;i<=n;i++){
		if(a[i]>=60){
			jige++;
		}
		if(a[i]>=85){
			youxiu++;
		}
	}
	printf("%.0lf%%\n%.0lf%%",jige*100/n,youxiu*100.0/n);
	return 0;
}

子串分值

#include
#include
using namespace std;
bool last[26];
string str;
long long judge(int x,int y){
	memset(last,0,sizeof(last));
	long long ans=0;
	for(int i=x;i<=y;i++){
		last[str[i]-'a']=1;
	}
	//ababc
	for(int i=0;i<=26;i++){
		ans+=last[i];
	}
	return ans;
}
int main(){
	cin>>str;
	int n=str.size();
	long long ans=0;
	for(int i=0;i<n;i++){
		for(int j=i;j<n;j++){
			ans+=judge(i,j);
		}
	}
	cout<<ans<<endl;
} 

年号子串

#include 
#include 
using namespace std;
int main(){
	stack<char>s; 
	int a;
	cin>>a;
	while(a){
		int x=a%26;
		if(x==0){
			x=26;
		}
		a=(a-x)/26;
		s.push('A'+x-1);
	}
	while(!s.empty()){
		cout<<s.top();
		s.pop();
	}
	return 0;
}


数列求值

#include 
using namespace std;
long long a[20190325];
int main(){
	a[1]=1;
	a[2]=1;
	a[3]=1;
	for(int i=4;i<=20190324;i++){
		a[i]=(a[i-1]+a[i-2]+a[i-3])%10000;
	}
	cout<<a[20190324]<<endl;
	return 0;
}

分解2019

#include 
using namespace std;

bool check(int x, int y, int z) {
	int res = 0;
	while (x) {
		res = x % 10;
		if (res == 2 || res == 4) return false;
		x /= 10;
	} 
	while (y) {
		res = y % 10;
		if (res == 2 || res == 4) return false;
		y /= 10;
	}
	while (z) {
		res = z % 10;
		if (res == 2 || res == 4) return false;
		z /= 10;
	}
	return true;
}

int main() {
	int ans = 0;
	for (int a = 1; a < 2019; a++) {
		for (int b = 1; b < 2019; b++) {
			if (b == a){
				continue;
			}
			for (int c = 1; c < 2019; c++) {
				if (b == c || a == c){
					continue;
				}
				if (a + b + c == 2019 && check(a, b, c)){
					ans++;
				}
			} 
		}
	}
	cout << ans / 6 << endl;
	return 0;
}

特别数字的和

#include
using namespace std;
bool check(int n){
	while(n){
		int temp=n%10;
		if(temp==0||temp==1||temp==2||temp==9){
			return true;
		}
		n/=10;
	}
	return false;
}
int main(){
	int ans;
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		if(check(i)){
			ans+=i;
		}
	}
	cout<<ans;
	return 0;
}

BFS

#include 
using namespace std;

char mp[30][50];
bool vis[30][50];
int dir[4][2] = {{1,0},{0,-1},{0,1},{-1,0}};
char dirc[4] = {'D','L','R','U'}; 
int n,m;

struct node{
	int x;	//横坐标 
	int y;	//纵坐标 
	int step;	//步数 
	string str;	//路径 
	node(int xx, int yy, int ss, string s) {	//构造函数 
		x = xx;
		y = yy;
		step = ss;
		str = s;
	}
}; 

queue<node> q; //创建队列

bool check(int x, int y) {	//判断是否越界以及是否是墙以及是否访问过了 
	if (x < 0 || x >= n || y < 0 || y >= m || vis[x][y] || mp[x][y] == '1') {
		return false;
	}
	return true;
}

void bfs(int x, int y) {
	q.push(node(x, y, 0, ""));
	vis[x][y] = true;
	while (!q.empty()) {
		node now = q.front();
		if (now.x == n - 1 && now.y == m - 1) {	//到达终点了 
			cout << now.str << endl;
			cout << now.step << endl;
			break;
		}
		q.pop();
		for (int i = 0; i < 4; i++) {
			int nx = now.x + dir[i][0];
			int ny = now.y + dir[i][1];
			if (check(nx, ny)) {
				q.push(node(nx, ny, now.step + 1, now.str + dirc[i]));
				vis[nx][ny] = true;
			}
		}
	}
} 

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 0; i < n; i++) {
		scanf("%s", mp[i]);
	}
	bfs(0, 0);
	return 0;
}

等差数列

#include
using namespace std;
int main(){
	int n,cha,ans;
	scanf("%d",&n);
	int a[100005];
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	sort(a+1,a+n+1);
	if(a[1]==a[n]){
		cout<<n<<endl;
	}else{
		cha=a[2]-a[1];
		ans=(a[n]-a[1])/cha+1;
		cout<<ans<<endl;
	}
	return 0;
}

换零钞

#include 
#include 
using namespace std; 
int main(){
	for(int i=1;i*5<=200;i++){
		for(int j=1;j<=200;j++){
			for(int k=1;k*2<=200;k++){
				if((k*2+j+i*5==200)&&(j*10==k)){
					cout<<i<<" "<<k<<" "<<j<<endl;
				}
			}
		}
	}
	return 0;
}

二维数组

#include
#include
int main(){
	char a[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	int n,m,i,j,k;
	scanf("%d%d",&n,&m);
	for(i=0;i<n;i++){
		for(j=0;j<m;j++){
			k=abs(i-j);
			printf("%c",a[k]);
		}
		printf("\n");
	}
	return 0;
}

长度

  1. sizeof运算符指出的是整个数组的长度
  2. strlen返回的是存储在数组中的字符串的长度,而非数组本身长度
  3. strlen只计算可见字符,而不会包含结束字符‘\0’
  4. 存储字符串到字符数组中要求数组长度至少为字符串长度strlen+1
  5. 字符串以‘\0’为结束标志

判断

#include 

在这个头文件里面
判断是否为十进制数字isdigit
如果 c 是一个数字,则该函数返回非零值,否则返回 0。
判断是否为字母isalpha
如果 c 是一个字母,则该函数返回非零值,否则返回 0。
判断是否为数字或者字母isalnum
如果 c 是一个数字或一个字母,则该函数返回非零值,否则返回 0

不可修改

const int * a;
const修饰的是整型数 int,而不是指针,即a是一个指向常整型数的指针。近一步的理解为:整型数 a是不可以被重新赋值的,而指针却是可以修改的,可以重新指向另外一个内存地址;
int * const a;
const修饰的是指针a,而不是整型数
a,*a为变量而不是一个常量。即a是指向一个可以修改的整型数的常指针。进一步的理解为:指针指向的整型数是可以被修改的,但是指针不可以被修改。
int const * a const;
a是指向一个常整型数的常指针,即指针不可修改,指针指向的整型数也是不可以被修改的。

小tips:

int型变量的一维数组最多是3千万,long long型1千5百万,char型1亿左右。

蓝桥杯不允许把int放在循环里面呜呜呜!!!!!!!!!

  • static会使定义的数据初始化为0
    技巧与memset(a,0,sizeof(a))一致
    后者可以初始化为别的数值
  • 2的整数次方的数的二进制里面只有一个1
  • 二进制表示浮点数方法:乘二挪整
  • 2个相同的二进制数做不进位加法,结果为0
  • 10个相同的十进制数做不进位加法,结果为0
  • k个相同的k进制数做不进位加法,结果为0
  • 四舍五入法在这里插入图片描述

考点

1、基本输入输出语法:
(1)如cin速度比scanf慢 两者遇到空格回车会停止读入
(2)若想读整行需要cin.getline()或gets函数
(3)读到文件尾用scanf()!=EOF等等
(4)占位符‘%’相关格式,如对齐方式,补0等。

#include
#include
//个人觉得可以用#include
using namespace std;
void main(){
int x=1000;
double y=1.23456789;
cout<<"默认x值:"<<x<<endl;
cout<<"十进制:"<<dec<<x<<endl;//decocthex会一直作用。
cout<<"八进制:"<<oct<<x<<endl;
cout<<"十六进制:"<<hex<<x<<endl;
cout<<"十六进制(大写字母):"<<hex<<uppercase<<x<<endl;
cout<<"默认y值(左对齐且有效数字位数为6):"<<y<<endl;
cout<<"宽度为10并右对齐:"<<setw(10)<<right<<y<<endl;
cout<<"宽度为4:"<<setw(4)<<y<<endl;
cout<<"用*号填充空位(10位宽度):"<<setfill('*')<<setw(10)<<y<<endl;//setw(inti)只对紧随的数据显示有影响。控制多个数据要多个setw()
cout<<"设精度为8输出y(不包括小数点):"<<setprecision(8)<<y<<endl;//如果小数位数不足8位,则输出完整的小数
cout<<"设精度为8输出y(不包括小数点):"<<fixed<<setprecision(8)<<y<<endl;//如果小数位数不足8位,则输出的小数结尾用0补齐8位
cout<<"显示正负号:"<<showpos<<y<<endl;
cout<<"用科学计数法表示y:"<<scientific<<y<<endl;
cout<<"用科学计数法表示y(控制E前数据的小数点后位数):"<<scientific<<setprecision(3)<<y<<endl;}

2、C/C++库函数以及stl模板
(1)algorithm: sort next_permutation ——gcd() lower_bound/upper_bound
(2)queue(priority_queue) stack vector set map基本操作等
3、数据结构
(1)结构体:注意结构体用sort排序,可自定义cmp函数
(2)字符串:string类的使用 查找首次出现的位置 统计总共出现的次数
(3)栈、队列:前缀、后缀表达式计算等。
(4)图:两种表示方法,邻接表和邻接矩阵,当n较大时只能采用邻接表。
(5)树:树是一种特殊的图。如按层输出节点等
(6)线段树:基本的单点修改、区间修改、区间查询等。
4、算法
(1)暴力:蓝桥杯又称暴力杯,n<=1e3(1000),O(n^ 2)的代码大概率能解,如果1e4<=n<=1e6,则要考虑O(n*logn)的算法,不过蓝桥按测试点得分,实在不会,可用O(n^2)骗分,骗到了就是赚到了。
(2)思维:不涉及算法,不涉及复杂数据结构,往往几行代码就可以解决,考验思维能力,多训练此类题目即可。
(3)模拟:模拟指根据题目描述,按部就班的写代码就可以AC,通常思路容易看出但是代码量较大,考验细节与心态。
①大数加减法
②进制转换
(4)数学问题:
①质数相关:埃式筛、欧拉筛、唯一分解定理等。
②求最大公因数:要自己会写gcd函数(欧几里得算法)
(5)贪心
(6)动态规划:
①最长公共子序列
③背包问题(01背包、多重背包、完全背包等)
(7)搜索:搜索基本是必考的点,包括DFS/BFS,可分别用栈和队列模拟。记忆化搜索也是常考的点,用于避免重复搜索。
(8)图论:
①最短路:最基本要掌握两种求法,floyd算法和dijkstra算法。前者O(n^3),适用于n不大于500的情况。后者dijkstra用的较多,数据结构实现有两种,邻接矩阵与邻接表,建议用邻接表(具体实现啊哈算法上有)。
②最小生成树:kruscal算法和prim算法
③拓扑排序
(9)字符串:回文、kmp算法(字符串匹配算法)
(10)其他:并查集、二分/三分算法等

你可能感兴趣的:(题解)