第十届蓝桥杯省赛B组题解记录

1.组队

思路:从每个位置可以选取的人选入手,每个人选不可重复,组合求最大。

方法一:深搜dfs

#include<bits/stdc++.h>
using namespace std;
int team[20][6],maxs=0,vis[20];
void dfs(int sum,int n)  //sum为出场运动员的分数求和 n为目前要选择的号位 
{
	if(n==6)
	{
		if(sum>maxs)
			maxs=sum;
		return ;
	}
	for(int i=0;i<20;i++)
	{
		if(!vis[i])
		{
			vis[i]=1;
			dfs(sum+team[i][n],n+1);
			vis[i]=0;	
		} 
	}
}
int main()
{
	freopen("201901.txt","r",stdin);  //放在当前目录下面 
	for(int i=0;i<20;i++)
	{
		for(int j=0;j<6;j++)
			cin>>team[i][j];
	}
	dfs(0,1);  //因为下标0是运动员编号 所以从1开始dfs 
	cout<<maxs;
}

方法二:多重循环

#include<bits/stdc++.h>
using namespace std;
int team[20][6],maxs=0,vis[20];

int main()
{
	freopen("201901.txt","r",stdin);  //放在当前目录下面 
	for(int i=0;i<20;i++)
	{
		for(int j=0;j<6;j++)
			cin>>team[i][j];
	}
	for(int i=0;i<20;i++)
	{
		for(int j=0;j<20;j++)
		{
			for(int k=0;k<20;k++)
			{
				for(int l=0;l<20;l++)
				{
					for(int m=0;m<20;m++)
					{
						if(i!=j&&i!=k&&i!=l&&i!=m&&j!=k&&j!=l&&j!=m&&k!=l&&k!=m&&l!=m)  //五个位置人员各不相同 
						{
							int s=team[i][1]+team[j][2]+team[k][3]+team[l][4]+team[m][5];
							if(s>maxs)
								maxs=s;
						}
					}
				} 
			} 
		}
	}
	cout<<maxs;
}

2.年号字符

思路:模拟26进制转换过程,个人认为栈很符合这个思想

#include<bits/stdc++.h>
using namespace std;
stack<int> ans;
int main()
{
	int n=2019;
	while(n)
	{
	    int t=n%26;
		ans.push(t);
		n/=26;
	}
	while(!ans.empty())
	{
		putchar('A'+ans.top()-1);
		ans.pop();
	}
	return 0;
}

3.数列求值

思路:模拟就好,没啥难的,注意取余就行

解法一:省内存,小动一下脑子

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int a[10]={1,1,1};
	for(int i=3;i<20190324;i++)
	{
		a[3]=(a[0]+a[1]+a[2])%10000;
		a[0]=a[1]%10000;
		a[1]=a[2]%10000;
		a[2]=a[3];
	}
	cout<<a[3];
	return 0;
}

解法二:开销大,很丝滑

#include<bits/stdc++.h>
using namespace std;
int a[20190324]={1,1,1};
int main()
{
	for(int i=3;i<20190324;i++)
	{
		a[i]=(a[i-3]+a[i-2]+a[i-1])%10000;
	}
	cout<<a[20190323];
	return 0;
}

4.数的分解

思路:挺简单的,暴力就行,也没啥坑

方法一:多重for循环

#include<bits/stdc++.h>
using namespace std;
int ans=0;
bool check(int n)
{
	while(n)
	{
		if(n%10==2||n%10==4)
			return false;
		n/=10;
	}
	return true;
}
int main()
{
	int d=2019/3;
	for(int i=1;i<=d;i++)
	{
		for(int j=i+1;j<=2*d;j++)
		{
			for(int k=j+1;k<2019;k++)
			{
				if(check(i)&&check(j)&&check(k)&&i+j+k==2019)
					ans++;
			}
		}
	}
	cout<<ans;
}

方法二:深搜dfs

#include<bits/stdc++.h>
using namespace std;
int ans=0,a[1100],count1=0;
void dfs(int sum,int n,int j)
{
	if(n==3)
	{
		if(sum==2019)
			ans++;
		return ;
	}
	for(int i=j;i<count1;i++)
	{
		dfs(sum+a[i],n+1,i+1); //和加上当前下标值 个数+1  下一个数开始的下标=当前下标+1 
	} 
}
int main()
{
	for(int i=1;i<=2019;i++)
	{
		int flag=0,t=i;
		while(t)
		{
			if(t%10==2||t%10==4)
			{
				flag=1;
				break;
			}
			t/=10;
		}
		if(!flag)
			a[count1++]=i;
	}
	dfs(0,0,0);  
	//前一个0代表此时和为0,第二个0代表目前总共有几个数 ,最后一个0记录“上一个已经用过的坐标 的下一个,即开始使用的第一个坐标”
	cout<<ans; 
}

5.迷宫

思路广搜常用于求最优化路径,注意点:a.路径相同输出ASCII码最小的,设置搜索顺序时按照ASCII由小到大即可;b.不用记录最短路径,只用记录每次的方向,因为第一个找到的值一定是最小的。深搜时,需要记录每次的方向和步数,因为第一次走到的不一定是步数最少的,注意点:得到结果比较时,<即可,=的话后面的字符串序列ASCII值更大。

解法一:bfs广搜

#include<bits/stdc++.h>
using namespace std;
char a[30][50]; 
int d[4][2]={{1,0},{0,-1},{0,1},{-1,0}};  //d,l,r,u
char dr[4]={'D','L','R','U'};
int vis[30][50];

struct node{
	int x,y;
	string str;
	node(int xx,int yy,string ss)  //构造函数 
	{
		x=xx;
		y=yy;
		str=ss;
	}
};

int MAP[30][50]{//迷宫
{0,1,0,1,0,1,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,1,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,1,0},
{0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,1,0,0,1,1,0,1,0,0,1,0,1},
{0,1,1,1,1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0},
{0,1,0,0,0,0,0,0,0,0,1,0,1,0,1,0,0,0,1,1,0,1,0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,1,0,1,1,0,0,1,0,1,1},
{0,0,0,1,1,1,1,1,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0},
{1,1,0,0,1,0,0,0,1,1,0,1,0,1,0,0,0,0,1,0,1,0,1,1,0,0,0,1,1,0,1,0,0,1,1,0,1,0,1,0,1,0,1,1,1,1,0,1,1,1},
{0,0,0,1,1,0,1,1,0,1,0,1,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,1,1,1,0,0,0,0,0,0,0},
{1,0,1,0,0,0,0,0,1,0,1,0,0,0,1,0,0,1,1,0,1,0,1,0,1,0,1,1,1,1,1,0,0,1,1,0,0,0,0,1,0,0,0,0,1,1,1,0,1,0},
{0,0,1,1,1,0,0,0,0,0,1,0,1,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,1,1,0,0,0,0,1,0,0,1},
{1,1,0,0,0,1,1,0,1,0,0,0,0,1,1,1,0,0,1,0,0,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,0,1,1,0,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,0,1,0,1,0,0,1,0,1,0,1,0,1,1,1,0,1,0,0,0,1,0,1,0,1,0,1,0,0,0,0,1,0,1},
{1,1,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,1,0,1,0,1,0,1,0,0,1,0,0,1,0,0,0,1,0,1,0,0},
{0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,1,1,0,0,1,1,1,1,0,1,0,0,0,1,1,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,1,1},
{1,0,1,0,1,0,1,0,0,1,1,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,1,0,1,1,0,0,1,1,1,1,0,1,1,0,1,0,0,0,0,1,0,0,0},
{1,0,1,0,1,0,1,0,1,0,0,0,0,1,1,0,1,0,1,0,1,0,0,1,0,1,0,0,0,0,1,0,1,0,0,0,0,0,1,1,1,0,1,1,1,0,1,0,0,1},
{1,0,0,0,0,0,0,0,1,0,1,1,0,0,0,1,0,0,0,0,1,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,1,0,0},
{1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,1,1,1,1,0,1,0,1,0,0,1},
{0,0,1,0,1,0,0,1,0,1,0,1,0,1,1,0,1,0,0,1,0,1,0,1,0,0,0,1,1,0,1,0,1,0,1,1,0,1,1,1,0,0,0,0,1,1,0,1,0,1},
{1,1,0,0,1,0,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,0,1,0},
{0,0,0,0,1,0,0,0,1,1,0,0,0,0,1,1,0,1,0,1,1,0,1,0,0,0,0,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,1,1,1,0,1},
{1,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,1,1,1,0,1,1,0,0,1,0,1,1,0,1,0,1,1,0,1,0,1,0,1,0,0,0,0,1},
{0,0,1,0,1,0,0,0,0,1,0,0,0,0,1,1,0,1,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,1,0,1},
{1,0,1,0,0,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,0,0,0,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,1,1,1,1,0,1,0,0,1,0},
{0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0},
{1,1,0,1,0,0,0,0,0,0,1,0,0,1,1,1,0,1,1,1,0,0,1,0,0,1,0,0,0,0,1,1,1,0,1,0,0,1,0,1,1,0,1,1,1,0,1,0,0,0},
{0,0,0,0,0,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,1,1,0,0,1,1},
{1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,1,0,0,0,1,0,1,0,1,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0},
{1,0,0,0,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,1,1,0,0,0,0,0,0,0,1,0,0,1,0,1,0,1,0,0,0,1,0,1,1,1,0,1,0,0,0},
{0,0,1,1,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,1,0,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,1},
{1,0,0,0,0,0,0,1,1,0,0,1,1,1,0,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,1,1,0,1,1,1,1,0,0,0}
};
queue<node> q;

bool check(int tx,int ty)  //检查下标是否越界,是否被访问过,是否有障碍 
{
//	cout<<tx<<" "<<ty<<" "<<vis[tx][ty]<<" "<<MAP[tx][ty]<<endl;
	if(tx<0||tx>=30||ty<0||ty>=50||vis[tx][ty]||MAP[tx][ty]==1)
		return false;
	return true;
}
void bfs()
{
	node no(0,0,"");
	q.push(no);
	vis[0][0]=1;
	while(!q.empty())
	{
		node t=q.front();
		if(t.x==29&&t.y==49)  //到达右下角 
		{
			cout<<t.str<<endl;
			break;
		}
		q.pop();
		for(int i=0;i<4;i++)
		{
			int tx=d[i][0]+t.x;
			int ty=d[i][1]+t.y;
			if(check(tx,ty))
			{
				q.push(node(tx,ty,t.str+dr[i]));
				vis[tx][ty]=1; 
			}
		}
	}
}
int main()
{
//	freopen("201901.txt","r",stdin);
//	for(int i=0;i<50;i++)
//	{
//		for(int j=0;j<30;j++)
//			cin>>a[i][j];
//	}
	
	bfs();
}

解法二:深搜(目测代码没问题,但是因为深搜,数据又很大,很久没跑出来,有问题大家可以给我说,我的代码给大家一个参考)

#include<bits/stdc++.h>
using namespace std;
char a[30][50]; 
int d[4][2]={{1,0},{0,-1},{0,1},{-1,0}};  //d,l,r,u
char dr[4]={'D','L','R','U'};
int vis[30][50];
int minStep=1000;
string minStr;


int MAP[30][50]{//迷宫
{0,1,0,1,0,1,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,1,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,1,0,1,0},
{0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,1,0,0,1,1,0,1,0,0,1,0,1},
{0,1,1,1,1,0,1,1,0,1,0,0,1,0,0,0,1,0,0,0,0,0,1,1,0,1,0,0,1,0,1,1,1,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0},
{0,1,0,0,0,0,0,0,0,0,1,0,1,0,1,0,0,0,1,1,0,1,0,0,0,0,1,0,1,0,0,0,0,0,1,0,1,0,1,0,1,0,1,1,0,0,1,0,1,1},
{0,0,0,1,1,1,1,1,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0},
{1,1,0,0,1,0,0,0,1,1,0,1,0,1,0,0,0,0,1,0,1,0,1,1,0,0,0,1,1,0,1,0,0,1,1,0,1,0,1,0,1,0,1,1,1,1,0,1,1,1},
{0,0,0,1,1,0,1,1,0,1,0,1,0,1,0,0,1,0,0,1,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,1,1,1,0,0,0,0,0,0,0},
{1,0,1,0,0,0,0,0,1,0,1,0,0,0,1,0,0,1,1,0,1,0,1,0,1,0,1,1,1,1,1,0,0,1,1,0,0,0,0,1,0,0,0,0,1,1,1,0,1,0},
{0,0,1,1,1,0,0,0,0,0,1,0,1,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,1,0,1,0,0,1,1,0,0,0,0,1,0,0,1},
{1,1,0,0,0,1,1,0,1,0,0,0,0,1,1,1,0,0,1,0,0,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,0,1,1,0,1,0,0,0},
{0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,0,1,0,1,0,0,1,0,1,0,1,0,1,1,1,0,1,0,0,0,1,0,1,0,1,0,1,0,0,0,0,1,0,1},
{1,1,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,1,0,1,0,1,0,1,0,1,0,0,1,0,0,1,0,0,0,1,0,1,0,0},
{0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,1,1,0,0,1,1,1,1,0,1,0,0,0,1,1,0,0,0,0,0,1,0,1,0,1,0,1,0,0,0,1,1},
{1,0,1,0,1,0,1,0,0,1,1,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,1,0,1,1,0,0,1,1,1,1,0,1,1,0,1,0,0,0,0,1,0,0,0},
{1,0,1,0,1,0,1,0,1,0,0,0,0,1,1,0,1,0,1,0,1,0,0,1,0,1,0,0,0,0,1,0,1,0,0,0,0,0,1,1,1,0,1,1,1,0,1,0,0,1},
{1,0,0,0,0,0,0,0,1,0,1,1,0,0,0,1,0,0,0,0,1,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,1,0,0},
{1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,1,1,1,1,0,1,0,1,0,0,1},
{0,0,1,0,1,0,0,1,0,1,0,1,0,1,1,0,1,0,0,1,0,1,0,1,0,0,0,1,1,0,1,0,1,0,1,1,0,1,1,1,0,0,0,0,1,1,0,1,0,1},
{1,1,0,0,1,0,1,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,1,0,1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,0,1,0},
{0,0,0,0,1,0,0,0,1,1,0,0,0,0,1,1,0,1,0,1,1,0,1,0,0,0,0,0,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,1,1,1,0,1},
{1,0,1,0,0,1,0,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,1,1,1,0,1,1,0,0,1,0,1,1,0,1,0,1,1,0,1,0,1,0,1,0,0,0,0,1},
{0,0,1,0,1,0,0,0,0,1,0,0,0,0,1,1,0,1,0,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,1,0,1},
{1,0,1,0,0,0,0,1,0,0,0,1,1,0,0,1,0,0,0,1,0,0,0,0,1,0,1,0,1,0,0,1,0,1,0,1,0,1,0,1,1,1,1,1,0,1,0,0,1,0},
{0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,1,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0},
{1,1,0,1,0,0,0,0,0,0,1,0,0,1,1,1,0,1,1,1,0,0,1,0,0,1,0,0,0,0,1,1,1,0,1,0,0,1,0,1,1,0,1,1,1,0,1,0,0,0},
{0,0,0,0,0,1,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,1,1,0,0,1,1},
{1,0,1,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,1,0,0,0,1,0,1,0,1,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0},
{1,0,0,0,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,0,1,1,0,0,0,0,0,0,0,1,0,0,1,0,1,0,1,0,0,0,1,0,1,1,1,0,1,0,0,0},
{0,0,1,1,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,1,0,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,1},
{1,0,0,0,0,0,0,1,1,0,0,1,1,1,0,1,0,1,1,1,0,1,0,0,0,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,1,1,0,1,1,1,1,0,0,0}
};

bool check(int tx,int ty)  //检查下标是否越界,是否被访问过,是否有障碍 
{
	if(tx<0||tx>=30||ty<0||ty>=50||vis[tx][ty]||MAP[tx][ty]==1)
		return false;
	return true;
}
void dfs(int x,int y,int step,string str)
{
//	cout<<x<<" "<<y<<" "<<step<<" "<<str<<endl;
	if(x<0||x>=30||y<0||y>=30||step>=minStep)
		return;
	if(x==29&&y==49)
	{
		if(step<minStep)
		{
			minStep=step;
			minStr=str;
			cout<<minStep<<" "<<minStr<<endl;
		}
		return ;
	}
	
	for(int i=0;i<4;i++)
	{
		int tx=x+d[i][0];
		int ty=y+d[i][1];
		if(!vis[tx][ty]&&MAP[tx][ty]==0)
		{
			vis[tx][ty]=1;
			dfs(tx,ty,step+1,str+dr[i]);
			vis[tx][ty]=0;
		}
	}
}
int main()
{
	dfs(0,0,0,"");
	cout<<minStr;
}

6.特别数的和

思路:很简单,模拟即可,也没坑

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n,ans=0;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
    	int t=i;
    	int flag=0;
    	while(t)
    	{
    		if(t%10==0||t%10==2||t%10==1||t%10==9)
    		{
    			flag=1;
    			break;
			}
			t/=10; 
		}
		if(flag)
			ans+=i;
	}
	cout<<ans;
}

7.完全二叉树的权值

思路:考察二叉树的性质,只要知道二叉树的每层的节点数是[2^{deep-1},2^{deep}-1],那就很好办,或者意识到每层的节点个数是1,2,4,....直到最后一层特别判断就好。

#include<bits/stdc++.h>
using namespace std;
int t;
int main(){
	int N;
	int deep = 1; //深度 
	long long sum = 0; //每行的和 
	long long max_sum = INT_MIN; //最大的和 
	int max_deep = 1;
	cin>>N;
	for(int i = 1; i <= N; ++i){
		cin>>t;
		sum += t;
		if(i == pow(2, deep) - 1){
			if(max_sum < sum){ //注意不要取等号,因为题目要最小的深度 
				max_deep = deep;
				max_sum = sum;
			}
			sum = 0;
			++deep;
			continue;
		}
		if(i==N)  //需要特判一下 如果不是满二叉树但是最后一层的值更大的话结果就不对
		{
		    if(max_sum < sum){ 
				max_deep = deep;
				max_sum = sum;
			}
		}
	}
	cout<<max_deep<<endl;
	return 0;
}

8.等差数列

思路: 明确等差是相邻两个数的差值,但并不是最小的那个差值就是最后要求的等差值,因为另外比他大的等差值可能没它大,但是他俩最大公约数为1,意味着这样求出来的等差数列肯定是错的。进而就能想到所有相邻数的差值的最大公约数即为整个序列的公差,那么序列的长度=(max-min)/公差+1.

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int A[N];
int n;

int gcd(int a,int b)  //求最大公约数
{
	while(b)
	{
		int t=a%b;
		a=b;
		b=t;
	}
	return a;
}

int main(){
	cin>>n;
	for(int i=0;i<n;i++)
		scanf("%d",&A[i]);
		
	sort(A,A+n);  //排序后方便比较
	
	int md=A[1]-A[0];
	if(md==0)  //这种情况是所有数相等 输出数的个数即可
	{
		cout<<n<<endl;
		return 0;
	}
	for(int i=2;i<n;i++)  //求所有相邻数插值的最大公约数
	{
		int t=A[i]-A[i-1];
		t=gcd(t,md);
		if(t<md)
			md=t;
	}
	cout<<(A[n-1]-A[0])/md+1<<endl;
	return 0;
}

9.后缀表达式

思路:

  • 没有减号,直接求和。
  • 有减号的情况

如果有负数存在的话:

  • 如果负数的个数num不等于n+m+1的话,我们是可以通过加括号的形式,将所有的减号变为加号的。-5 -4 -3 -2 1,+++-,1-(
  • 如果负数的个数num等于n+m+1的话,肯定会留出一个负数来,无法通过加括号的形式变为正的,那么就只能加上这个负数,贪心去想,肯定是负数中最大的那个(绝对值最小的那个)。-5 -4 -3 -2 -1,+++-,-1-(),,,++--,

-1-((-5+(-4)+(-3))-(-2)

如果说没有负数的话,那么只能减去最小的那个数,剩下的就可以通过加括号的形式变为加了。如,1,2,3,4,5,两个+,两个-,则为5+4+3-(1-2)

1,2,3,4,5 +++-,2+3+4+5-1

1,2,3,4,5 +---,5+4-(1-2-3)

坑点:注意数组开2e5+100, 因为N or M小于1e5,两个加起来开小了数组会越界;另外计算的时候注意负数相加的个数。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAX=2e5+100;
int N,M,num;
int A[MAX];
LL sum=0;
int main(){
	cin>>N>>M;
	for(int i=0;i<=N+M;i++)
	{
		scanf("%d",&A[i]);
		sum+=A[i];
		if(A[i]<0)
			num++;  //记录负数的个数 
	}
	sort(A,A+N+M+1);
	if(M==0)  //全是+
	{
		cout<<sum<<endl;
		return 0;
	} 
	// 存在- 
	// 分为两大类: 1.有负数:a.负数的数目等于N+M+1(即全负数),绝对值求和+2*最大的负数 ;b.负数个数小于N+M+1,将所有的数绝对值求和
	// 2.无负数:所有的数求和-2*最小数 
	if(num)  //存在- 
	{
		if(num==N+M+1)  //全为负数 
		{
			for(int i=0;i<N+M;i++)	
				sum-=2*A[i]; 
		}
		else  //存在正数 
		{
			for(int i=0;i<num;i++)
				sum-=2*A[i];
		}
	} 
	else  //存在-且全为负数 
	{
		sum-=2*(A[0]);
	}
	
	cout<<sum;
	return 0;
}

10.灵能传输

思路:前缀和+排序+贪心,详情思路请见yxc的视频,我只能说yyds

坑点:暂存s0和sn时别忘了用LL,不然会溢出,另外注意处理f数组的顺序

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAX=3e5+10;
int T;
LL a[MAX];
LL s[MAX],f[MAX];
bool st[MAX];
int main(){
	cin>>T;
	while(T--)
	{
		int n;
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			scanf("%lld",&a[i]);
			s[i]=s[i-1]+a[i];  //计算前缀和 
		}
	
		LL s0=s[0],sn=s[n];
		if(s0>sn)
			swap(s0,sn);
		sort(s,s+n+1);
		
		
		for(int i=0;i<=n;i++)  //确定s0排序后的位置 
		{
			if(s0==s[i])
			{
				s0=i;
				break;
			}
		}
		
		for(int i=n;i>=0;i--)  //确定sn排序后的位置  从右往左是保证sn一定在s0右边 即使两数相等 
		{
			if(sn==s[i])
			{
				sn=i;
				break;
			}
		}
		
		memset(st,false,sizeof st);  //用st数组标记哪些数字已经走过 
		int l=0,r=n;
		for(int i=s0;i>=0;i-=2)  //从s0往左跳 
		{
			f[l++]=s[i];
			st[i]=true;
		}
		
		for(int i=sn;i<=n;i+=2)  //从sn往右跳 
		{
			f[r--]=s[i];
			st[i]=true;
		}
		
		for(int i=0;i<=n;i++)
		{
			if(st[i]==false)
			{
				f[l++]=s[i];
			}
		}
		LL ans=0;
		for(int i=1;i<=n;i++)
		{
			ans=max(abs(f[i]-f[i-1]),ans);
		}
		cout<<ans<<endl;
	}
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值