第一题 AcWing 4944. 热身计算
一、题目
1、原题链接
4944. 热身计算
2、题目描述
输入格式
共一行,包含两个正整数 a,b。
输出格式
共一行,输出两个整数,分别表示 min(a,b) 以及 ⌊|a−b|/2⌋。
数据范围 所有测试点满足 1≤a,b≤100。
输入样例1:
3 1
输出样例1:
1 1
输入样例2:
2 3
输出样例2:
2 0
输入样例3:
7 3
输出样例3:
3 2
二、解题报告
1、思路分析
直接按题意进行模拟即可。
2、时间复杂度
时间复杂度为O(1)
3、代码详解
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int a,b;
int main(){
cin>>a>>b;
cout<<min(a,b)<<' '<<abs(a-b)/2;
return 0;
}
第二题 AcWing 4945. 比大小
一、题目
1、原题链接
4945. 比大小
2、题目描述
给定一个 n 位 bx 进制数 X 和一个 m 位 by 进制数 Y。
X 和 Y 都为正整数,且都不含前导 0。
请你比较它们的大小。
输入格式
第一行包含两个整数 n,bx。
第二行包含 n 个整数 x1,x2,…,xn,表示 X 的各位数字,它们按照从最高有效位到最低有效位的顺序给出。
第三行包含两个整数 m,by。
第四行包含 m 个整数 y1,y2,…,ym,表示 Y 的各位数字,它们按照从最高有效位到最低有效位的顺序给出。
X 和 Y 的各位数字在输入中均按十进制表示给出。
输出格式
共一行:
如果 X<Y,则输出 <。
如果 X>Y,则输出 >。
如果 X=Y,则输出 =。
数据范围
前 6 个测试点满足 2≤bx,by≤16。 所有测试点满足
1≤n,m≤10,2≤bx,by≤40,bx≠by,0≤xi<bx,0≤yi<by。
输入样例1:
6 2
1 0 1 1 1 1
2 10
4 7
输出样例1:
=
输入样例2:
3 3
1 0 2
2 5
2 4
输出样例2:
<
输入样例3:
7 16
15 15 4 0 0 7 10
7 9
4 8 0 3 1 5 0
输出样例3:
>
二、解题报告
1、思路分析
(1)题目考察进制转换,正好也是蓝桥杯常考点,我在蓝桥杯考前知识点总结中正好总结了该知识点。
(2)利用秦九韶算法进行n进制转十进制,然后比较大小即可。
(3)注意开long long:数字最多10位,最大进制为40,所以结果最大可能为4010,会超int。(比赛时由于没开long long最后两个测试点过不了)。
2、时间复杂度
时间复杂度O(n)
3、代码详解
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL; //注意数据范围,要开long long
const int N=15;
int x[N],y[N];
int n,bx,m,by;
//秦九韶算法进行n进制转十进制
LL ntoten(int a[],int num,int n){
LL res=0;
for(int i=0;i<num;i++){
res=res*n+a[i];
}
return res;
}
int main(){
cin>>n>>bx;
for(int i=0;i<n;i++) cin>>x[i];
cin>>m>>by;
for(int i=0;i<m;i++) cin>>y[i];
LL xs=ntoten(x,n,bx),ys=ntoten(y,m,by);
if(xs<ys) cout<<'<';
else if(xs>ys) cout<<'>';
else cout<<'=';
return 0;
}
第三题 AcWing 4946. 叶子节点
一、题目
1、原题链接
4946. 叶子节点
2、题目描述
给定一棵 n 个节点的树,节点编号 1∼n。
1 号节点为树的根节点。
每个节点要么是黑色的,要么是白色的。
对于一个叶子节点,如果从该节点到根节点的路径(包括两端节点)中有超过 m
个黑色节点连续的排列在一起,则称该节点为无效叶子节点。
有效叶子节点数量 = 总叶子节点数量 - 无效叶子节点数量
请你统计,给定树中有效叶子节点的数量 。
输入格式
第一行包含两个整数 n,m。
第二行包含 n 个整数 a1,a2,…,an,其中 ai 表示第 i 个节点的颜色,1 表示黑色,0 表示白色。
接下来 n−1 行,每行包含两个整数 x,y,表示节点 x 和节点 y 之间存在一条无向边。
保证输入给定的是一棵树。
输出格式
一个整数,表示给定树中有效叶子节点的数量。
数据范围
前 6 个测试点满足 2≤n≤10。 所有测试点满足 2≤n≤105,1≤m≤n,0≤ai≤1,1≤x,y≤n,x≠y。
输入样例1:
4 1
1 1 0 0
1 2
1 3
1 4
输出样例1:
2
输入样例2:
7 1
1 0 1 1 0 0 0
1 2
1 3
2 4
2 5
3 6
3 7
输出样例2:
2
二、解题报告
1、思路分析
思路来源:y总讲解视频
y总yyds
(1)树的遍历同时维护两个信息,即走到当前点已经连续黑色节点的个数和当前路径是否已经存在连续黑色节点的数量超过m个(即存储当前路径子节点是否为有效节点)。
(2)dfs进行遍历维护即可。
(3)注意子节点的判断:由于存储的是无向边,所以针对子节点只存储一条它和其父节点的一条边,所以遍历子节点的每条边,判断是否只存在一条指向其父节点的边即可。
2、时间复杂度
时间复杂度O(n)
3、代码详解
#include <iostream>
#include <cstring>
using namespace std;
const int N=100010,M=2*N; //无向边存两条
int h[N],color[N],e[M],ne[M],idx; //邻接表存储每条无向边,color[]存储每个点的颜色
int n,m;
//邻接表加边
void add(int a,int b){
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
//dfs遍历树,u为当前节点,fa为u的父节点,num为走到当前点已经存在的连续的黑色节点的个数,flag代表是否已经存在超过m个连续节点(针对叶子节点即代表是否为有效节点)
//返回从当前根开始遍历的有效子节点数
int dfs(int u,int fa,int num,bool flag){
if(color[u]==1) num++; //如果当前点为黑色,连续黑色节点数+1
else num=0; //否则,当前连续黑色节点数清空
if(num>m) flag=false; //如果连续黑色节点数已超过m,标记该条路径上的叶子节点为无效节点
int ans=0,sons=0; //ans记录答案,sons记录u的子节点数
for(int i=h[u];i!=-1;i=ne[i]){ //遍历每条边
int j=e[i]; //取出每条边的终点
if(j==fa) continue; //如果边终点是父节点,continue,因为要向下遍历
sons++; //否则子节点数+1
ans+=dfs(j,u,num,flag); //继续向下遍历
}
if(!sons&&flag) ans++; //如果该节点没有子节点(即为叶子节点)而且是有效节点,ans++
return ans; //返回ans即可
}
int main(){
cin>>n>>m;
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++) cin>>color[i];
for(int i=0;i<n-1;i++){
int x,y;
cin>>x>>y;
add(x,y),add(y,x);
}
cout<<dfs(1,-1,0,true);
return 0;
}