【2023蓝桥杯】2019年第十届C/C++A组真题(解析笔记)

目录

【平方和】

【数列求值】

【最大降雨量】

【迷宫】 

【RSA解密】

【完全二叉树的权值】

【外卖店优先级】

【修改数组】

【糖果】

【组合数问题】 

 【平方和】

long long;

填空题可以尝试小的数字,判断程序是否正确!

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;  //long long  
long long ans=0;
//只要含有0,1,2,9都算 
int check(int x){
	while(x){
		int t=x%10; //求余数
		if(t==0||t==1||t==2||t==9)  
			return 1;
		x/=10; //求整 
	} 
	return 0; 
}

int main(){
	for(int i=1;i<=2019;i++){
		if(check(i))  ans+=i*i;
	} 
	cout<<ans<<endl;
	return 0;
} 

【数列求值】

蓝桥杯第 8-10 届真题解析 - 《数列求值》名师讲解     

同余理论!

可以用Excel确保编程正确!

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

int main(){
    int t1=1, t2=1, t3=1, t4 ;
	for(int i=4;i<=20190324;i++){
		t4=(t1+t2+t3)%10000;
		t1=t2; t2=t3; t3=t4;	
	} 
	cout<<t4<<endl;
	return 0;
} 

 【最大降雨量】

 思维能力,无需编程!绝!推理题

【迷宫】 

#include<bits/stdc++.h>
#include<queue> 
#include<string>
using namespace std;
//4行6列 
#define ROWS 4
#define COLS 6
//二维数组 
string maze[ROWS+2]={
	"010000",
	"000100",
	"001001",
	"110000"
}; 

//4个方向 
int dir[4][2]={
   
   {1,0},{0,-1},{0,1},{-1,0}}; //D L R U
char dirs[5]="DLRU";

//定义结构体,结点到达的每一个位置 
struct node{
	int x,y;    //X行y列 
	char pos;	//从上一个结点(父节点)到达当前结点所走的方向 DLRU 
};

//代表每一个位置有没有走过 
int visited[ROWS+2][COLS+2]; //稍微大一些,不能扣 ,0表示未访问过 
//队列 node数据 
queue<node> Q;
//每个位置[x][y]的父结点(上一个结点)father[x][y] 
node father[ROWS+2][COLS+2];
//是否出边界
int in(int tx, int ty){
	return (tx>=0&&tx<ROWS&&ty>=0&&ty<COLS);
} 
//伸缩函数
void dfs(int x, int y){
	if(x==0&&y==0)
		return; //找到入口就不再递归下去
	else{
		dfs(father[x][y].x,father[x][y].y);
		cout<<father[x][y].pos; //因为是在回退时输出“路径”(上的字符) ,所以应该在这里输出 
	} 
} 
int main(){
	node start, now, next; //定义结点,起始结点,当前结点,下一个结点 
	int i, tx, ty; //走到(x,y) 的下一个坐标 (tx,ty)
	start.x =0; start.y=0;//构造起始结点 
	Q.push(start); 
	visited[0][0]=1; //进行入队列 
	while(!Q.empty()){
		now=Q.front(); //取出当前结点 
		Q.pop(); 
		if(now.x==ROWS-1&&now.y==COLS-1) break;
		for(i=0; i<4;i++){ //检查4个方向 
			tx=now.x+dir[i][0];
			ty=now.y+dir[i][1];
			if(in(tx,ty)&&maze[tx][ty]=='0'&&visited[tx][ty]==0){
				visited[tx][ty]=1;
				father[tx][ty].x=now.x;
				father[tx][ty].y=now.y;
				father[tx][ty].pos=dirs[i];
				next.x=tx;
				next.y=ty;
				Q.push(next); //入队列 
			}
		}
	}
	dfs(ROWS-1,COLS-1); 
	return 0;
}

【RSA解密】

 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
//扩展欧几里得求逆元(a和b互质) 
ll ext_gcd(ll a, ll b, ll& x, ll&y){
	int t, ret;
	if(!b){ //b==0
		x=1, y=0;
		return a;
	} 
	ret=ext_gcd(b, a%b, x, y);
	t=x, x=y, y=t-a/b*y;  //x是a对模b的逆元,y是b对模a的逆元 
	return ret;
}

//求(x*y)%p (快速乘,防止爆long long) 
inline ll mul(ll x, ll y, ll p){
	ll z=(long double)x /p*y;
	ll res=(unsigned long long)x*y-(unsigned long long)z*p;
	return (res+p)%p;
} 

//fpm 快速幂 求X=C^e mod n 并返回X 
ll fpm(ll C, ll e, ll n){
	C%=n;
	ll ans=1;
	for(; e; e>>=1, C=mul(C,C,n)) //e>>=1:e 右移一位并赋值给e,即 e/=2 
		if(e&1)	(ans=mul(ans, C,n))%=n; //& 按位与? 
	return ans;
} 
 
//C=20190324, e=823816093931522017, n=1001733993063167141
ll power(ll C, ll e, ll n){	//求X=C^e mod n 并返回X 
	ll i, ans=1;
	for(i=1; i<=e; i++)
		ans=(ans*C)%n;
	return ans;
}
int main() {
	ll n=1001733993063167141, d=212353, p, q;
	//暴力枚举求p,q 
	for(ll i=3; i*i<n; i+=2){
		if(n%i==0){ //n%i==0 首个满足if条件的i一定为素数 
			p=i; q=n/i; break;
		}
	}
//	cout<<"p="<<p<<endl; 
//	cout<<"q="<<q<<endl; 
	p=891234941;
	q=1123984201;
	
	ll e, m=(p-1)*(q-1), x, y;
	ext_gcd(d, m, x, y); 	//x是d对模m的逆元,y是m对模d的逆元 
	e=(x%m+m)%m;			//防止x<0或x>m作的修正 
//	cout<<"e="<<e<<endl; 	//e=823816093931522017 意味着 
	
	ll C=20190324; 
	//cout<<power(C,e,n) <<endl; 	//求X=C^e mod n并输出X(估计至少要运行100年) 
	cout<<fpm(C,e,n)<<endl;			//求X=C^e mod n并输出X (快速幂算法)
	return 0; 	
}

【完全二叉树的权值】

比赛时,多拟几组数据,确保编程正确!

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

int main() {
	ll maxsum = -755360000011, sum; //最大和,每层整数和
	int N, num, cnt=0;
	int flag =0; //flag为 1表示已经读入了所有的整数
	int layer,maxlayer=1;
	int i;
	cin>>N;
	//读入每一层的结点,根结点为第一层 
	for(layer=1; ;layer++){
		sum=0;
		//读入每层layer的所有结点,2^(layer-1) 
		for(i=0;i<(1<<(layer-1));i++ ) //1按位左移计算,二进制左移 
		{
			cin>>num;
			sum+=num;
			//已读入的整数个数已经到达了N个 
			if(++cnt>=N){
				flag = 1; break;
			}
		 } 
		 //一层 
		 if(sum>maxsum){
		 	maxsum=sum;
		 	maxlayer=layer;
		 } 
		 if(flag) break; 
	} 
	cout<<maxlayer<<endl;
	return 0;
}

【外卖店优先级】

 

#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int MAXN=100010;
const int MAXM=100010;

int N,M,T;
int priority[MAXN];//priority记录外卖店优先级(初值为0)
int last[MAXN];//Last记录外卖店上一个订单的时刻(初值为0)
bool st[MAXN];//外卖店是否在优先缓存中的标志
PII order[MAXM];//每个订单的时刻(ts)及外卖店(id)


int  main()
{
	int i,j;
	scanf("%d%d%d", &N, &M, &T);
	for(i=0; i<M; i++)
		scanf("%d%d", &order[i].first, &order[i].second);
		sort(order,order + M);//按照订单时间先后排序,时间相同再按外卖店序号从小到大排序
		for(i = 0; i<M;){//只考虑有订单的时刻(即M条订单)
			j = i;
			while(j< M && order[j]==order[i]) j++;//同一时间同一店铺有多条订单
			
			int t = order[i].first,id = order[i].second, cnt = j-i;//订单数
			i=j;
			priority[id] -= t-last[id] - 1;//先减去没有订单的优先级
			if(priority[id]<0) priority[id] =0;//优先级最低为0
			if(priority[id]<=3) st[id] = false;//出缓存
			priority[id] += cnt*2;//加上cnt个订单带来的优先级
			if(priority[id] >5) st[id] = true;//进缓存
			last[id] = t;//维护last
		}
		for(i = 1; i <= N; i++){//最后T时刻更新所有店铺优先级
			if(last[i]<T){
				priority[i]-=T-last[i];
				if(priority[i]<=3) st[i]=false;
			}
		}
		int ans = 0;//最终答案:在优先缓存中的外卖店数量
		for(i = 1; i <=N; i++ ) ans+= st[i];
		printf("%d\n",ans);
		return 0;

}

【修改数组】

 

 

 80%

#include<bits/stdc++.h>
#include<time.h> 
using namespace std;
#define MAXN 100005
#define MAXA 100005
int A[MAXN];
int bused[MAXA];//1~100000o是否已经出现过的标志
int main( )
{ 
	//freopen("d2.in","r", stdin);
	// freopen("d2.out","w", stdout);
	time_t time, start, end;//程序运行总时间、程序运行开始时刻、结束时刻
	start = clock( );//取得系统当前时刻
	int i,j,N;
	scanf( "%d",&N);
	for(i = 1; i<=N; i++)
		scanf( "%d",&A[i]);
	bused[A[1]]= 1;
	for(i=2; i<=N; i++){//调整A[i]:检查A[1]~A[i-1]
		if( !bused[A[i]]){ //A[i]没有出现过,直接在bused数组里将A[i]所处位置标志置1
		bused[A[i]] = 1; continue;
		}
		do{//A[i]已经出现过,则A[i]增加1,再判断A[i]you| 
			A[i]++;
		}while(bused[A[i]]);
		bused[A[i]]= 1;
	} 
	for(i = 1; i <N; i++)
		printf("%d ",A[i]);
	printf("%d\n",A[N]);
	end = clock( );//取得系统当前时刻
	time = end - start;
	// printf("%d\n", time );
	return 0;
} 

100% 并长集 -高手入

 【糖果】

【组合数问题】 

【指路】蓝桥杯第 8-10 届真题解析 - 《组合数问题》名师讲解 - 蓝桥云课 (lanqiao.cn)

 

猜你喜欢

转载自blog.csdn.net/MengYa_Dream/article/details/129353971