洛谷 B4063 [GESP202412 一级] 奇数和偶数

点点关注(花花花)

恩师:hnjzsyjyj

一、题目介绍:初识奇数和偶数问题

大家好呀!今天咱们要一起学习洛谷上的一道基础编程题 ——B4063 [GESP202412 一级] 奇数和偶数。这道题是 GESP 一级考试的真题,难度非常适合编程入门者,主要考察对 “奇数偶数判断” 和 “循环计数” 的基本掌握。哪怕你是刚接触编程的新手,跟着我一步步分析,也能轻松学会这道题的解法哦~

1.1 题目来源与定位

洛谷 B4063 来自 2024 年 12 月的 GESP 一级考试,难度评级为 “入门”。它是编程初学者的经典练习题,主要考察三个核心知识点:

  • 基本输入输出(读取数据、输出结果)
  • 分支判断(if 语句判断奇偶数)
  • 循环结构(while 循环处理多个数据)
  • 计数器的使用(统计奇数和偶数的数量)

这道题虽然简单,但却是理解 “条件判断” 和 “循环统计” 的基础,学会它能为后续更复杂的编程题打下扎实的基础。

1.2 题目描述

咱们先来明确题目要求,用最通俗的话来讲:

题目需要我们写一个程序,完成以下操作:

  1. 首先输入一个整数n,表示接下来有n个整数要处理;
  2. 然后依次输入n个整数;
  3. 统计这n个整数中,奇数有多少个偶数有多少个
  4. 最后输出两个结果:第一个是奇数的数量,第二个是偶数的数量,中间用空格隔开。

什么是奇数和偶数呢?简单复习一下数学知识:

  • 偶数:能被 2 整除的整数,比如 0、2、4、6、8……
  • 奇数:不能被 2 整除的整数,比如 1、3、5、7、9……
  • 判断方法:一个数除以 2 的余数如果是 1,就是奇数;余数是 0,就是偶数。

1.3 输入输出示例

为了更清楚理解题目,咱们看两个示例:

示例 1

  • 输入:3(表示有 3 个整数)
  • 接着输入:1 2 3
  • 分析:1 是奇数,2 是偶数,3 是奇数
  • 奇数数量:2,偶数数量:1
  • 输出:2 1

示例 2

  • 输入:5
  • 接着输入:10 15 0 7 22
  • 分析:10(偶)、15(奇)、0(偶)、7(奇)、22(偶)
  • 奇数数量:2,偶数数量:3
  • 输出:2 3

通过示例可以看出,0 是偶数哦!这一点初学者容易忽略,要特别注意~

1.4 题目难度与适合人群

这道题是 GESP 一级的题目,难度非常基础,适合以下人群:

  • 刚接触 C++ 编程的初学者(学习时间 1-2 个月)
  • 已经掌握变量定义、输入输出、if 语句和循环的同学
  • 想巩固 “条件判断” 和 “计数器” 用法的编程爱好者

如果你能看懂简单的if语句和while循环,这道题对你来说会很轻松。即使是纯新手,跟着我的思路一步步来,也能很快学会~

二、解题思路:三步搞定奇偶数统计

面对编程题,不要急着写代码,先理清思路最重要。解决 “奇数和偶数” 问题可以分三步:读取输入数据→判断每个数是奇数还是偶数→统计数量并输出。咱们详细分析每一步的逻辑~

2.1 第一步:明确需要的变量

编程的第一步是想清楚需要哪些 “容器” 来存储数据,也就是变量。这道题需要的变量有:

  • n:用来存储输入的整数总个数(比如示例 1 中的 3)
  • a:临时存储每次输入的整数(比如 1、2、3)
  • ans1:计数器,统计奇数的数量(初始值为 0)
  • ans2:计数器,统计偶数的数量(初始值为 0)

这些变量就像我们的 “工具包”,n是任务清单,a是当前处理的物品,ans1ans2是两个计数器,分别记录奇数和偶数的数量。

2.2 第二步:读取数据并循环处理

题目要求先输入n,再输入n个整数。这意味着:

  1. 先用cin读取n的值;
  2. 然后循环n次,每次读取一个整数到a中;
  3. 对每个a进行判断:是奇数就给ans1加 1,是偶数就给ans2加 1。

循环就像工厂的流水线,n是产品总数,每个a是流水线上的产品,我们需要逐个检查并分类计数。

2.3 第三步:判断奇偶数的核心逻辑

判断一个数是奇数还是偶数的核心是看它除以 2 的余数:

  • 如果a % 2 != 0(余数不是 0),说明是奇数,ans1++
  • 否则(余数是 0),说明是偶数,ans2++

这里的%是取余运算符,a % 2就是计算a除以 2 的余数。比如:

  • 3 % 2 = 11 != 0→奇数→ans1++
  • 4 % 2 = 00 == 0→偶数→ans2++
  • 0 % 2 = 0→偶数→ans2++(记住 0 是偶数哦!)

2.4 完整流程总结

把三步思路串起来,完整的流程就是:

  1. 定义变量naans1ans2(其中ans1ans2初始为 0);
  2. 读取n的值;
  3. 循环n次:
    • 读取整数到a
    • 判断a是奇数还是偶数;
    • 对应计数器加 1;
  4. 循环结束后,输出ans1ans2

这个流程就像咱们整理水果:先知道有多少个水果(n),然后逐个检查每个水果是苹果还是香蕉(奇还是偶),分别放在两个篮子里(ans1ans2),最后告诉别人每个篮子里有多少个水果。

三、代码解析:逐行读懂奇偶数统计的实现

根据上面的解题思路,用户提供的代码完美实现了所有功能。咱们逐行分析这段代码,看看它是如何一步步工作的:

cpp

#include<bits/stdc++.h>
using namespace std;
int n,a,ans1,ans2;
int main(){
	cin>>n;
	while(n--){
		cin>>a;
		if(a%2!=0)ans1++;
		else ans2++;
	}
	cout<<ans1<<" "<<ans2;
    return 0;
}

这段代码非常简短,但逻辑完整,咱们逐行拆解:

3.1 头文件与命名空间:代码的 “基础配置”

cpp

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

这两行是 C++ 代码的标准开头,作用是:

  • #include<bits/stdc++.h>:引入 C++ 的 “万能头文件”,它包含了所有常用的标准库(比如输入输出、数学运算等),省去了我们逐个引入头文件的麻烦。对于初学者来说,记住这一行就够了,不用纠结具体包含了什么。
  • using namespace std;:声明使用标准命名空间。C++ 的很多函数(比如cincout)都在std这个命名空间里,加上这句话,我们就可以直接写cin而不用写std::cin,简化代码。

这两行代码就像我们写作文时的 “纸和笔”,是基础工具,几乎所有 C++ 程序都会用到~

3.2 变量定义:准备 “工具包”

cpp

int n,a,ans1,ans2;

这行代码定义了 4 个整数变量,它们的作用在 2.1 节已经讲过:

  • n:存储整数的总个数
  • a:临时存储当前输入的整数
  • ans1:奇数计数器(初始值为 0,因为全局变量默认初始值为 0)
  • ans2:偶数计数器(初始值为 0)

这里要注意:变量定义在main函数外面(全局变量),所以ans1ans2会自动初始化为 0。如果定义在main函数内部,需要手动初始化(比如int ans1 = 0;),否则初始值是随机的,会导致统计错误!

3.3 主函数:程序的 “核心工厂”

main函数是程序的入口,所有操作都在这里执行,就像工厂的核心车间。咱们一步步看:

3.3.1 读取整数个数 n

cpp

cin>>n;

这行代码通过cin从输入设备(比如键盘)读取n的值。比如输入3n就等于 3,告诉程序接下来要处理 3 个整数。

cin是 C++ 的输入函数,>>是输入运算符,作用是把输入的数据 “流” 到变量里。可以理解为 “把键盘输入的数放到n这个盒子里”。

3.3.2 循环处理 n 个整数

cpp

while(n--){
    // 循环体:读取a并判断
}

这是一个while循环,作用是重复执行n次操作。n--是 “先判断后减 1” 的意思:

  • 第一次循环时,判断n是否大于 0(此时n是初始值,比如 3);
  • 执行循环体;
  • 循环体结束后,n的值减 1(3→2→1→0);
  • n减到 0 时,循环结束(因为 0 表示假,循环停止)。

这个循环就像一个倒计时器,n是初始时间,每次循环后时间减 1,直到时间为 0,共执行n次循环。

3.3.3 读取当前整数 a

cpp

cin>>a;

在循环体内部,这行代码每次读取一个整数,存储到a中。比如第一次循环读取 1,a=1;第二次读取 2,a=2;第三次读取 3,a=3

a就像一个 “临时托盘”,每次装一个整数,处理完后再装下一个。

3.3.4 判断奇偶数并计数

cpp

if(a%2!=0)ans1++;
else ans2++;

这是整个程序的核心判断逻辑,用if-else语句实现:

  • a%2:计算a除以 2 的余数(比如3%2=14%2=0);
  • a%2!=0:如果余数不等于 0(即余数是 1),说明是奇数,执行ans1++ans1的值加 1);
  • else:否则(余数是 0),说明是偶数,执行ans2++ans2的值加 1)。

举个例子,当a=1时:

  • 1%2=11!=0为真,所以ans1从 0 变成 1;
    a=2时:
  • 2%2=00!=0为假,执行elseans2从 0 变成 1;
    a=3时:
  • 3%2=1ans1从 1 变成 2。

这样循环结束后,ans1=2(奇数个数),ans2=1(偶数个数),和示例 1 的结果一致~

3.3.5 输出结果

cpp

cout<<ans1<<" "<<ans2;

循环结束后,ans1ans2分别存储了奇数和偶数的数量。这行代码通过cout输出两个结果:

  • 第一个是ans1(奇数数量);
  • 中间用空格隔开(" ");
  • 第二个是ans2(偶数数量)。

cout是 C++ 的输出函数,<<是输出运算符,作用是把变量的值 “流” 到屏幕上。比如ans1=2ans2=1,就会在屏幕上输出2 1

3.3.6 程序结束

cpp

return 0;

表示main函数执行完毕,程序正常退出。这行代码是 C++ 程序的规范结尾,告诉操作系统程序成功运行结束。

3.4 完整代码执行流程

为了让大家更清晰理解,咱们用示例 1(输入3 1 2 3)完整演示程序的执行过程:

  1. 初始状态n未赋值,a未赋值,ans1=0ans2=0
  2. 读取 ncin>>n后,n=3
  3. 第一次循环(n=3→2)
    • cin>>a读取 1,a=1
    • a%2=11!=0为真,ans1++ans1=1
  4. 第二次循环(n=2→1)
    • cin>>a读取 2,a=2
    • a%2=00!=0为假,ans2++ans2=1
  5. 第三次循环(n=1→0)
    • cin>>a读取 3,a=3
    • a%2=11!=0为真,ans1++ans1=2
  6. 循环结束(n=0)
    • 执行cout<<ans1<<" "<<ans2,输出2 1
  7. 程序结束return 0

整个过程就像流水线作业,每个数都被正确判断并计数,最终输出结果。

四、核心知识点详解:搞懂每个关键概念

这道题虽然简单,但包含了几个重要的编程基础知识点,咱们逐个详解,帮你彻底理解~

4.1 变量定义与初始化

变量是编程的基础,就像我们生活中的盒子,用来装数据。在 C++ 中定义变量的格式是:数据类型 变量名;

这道题用的是int类型(整数类型),可以存储正整数、负整数和 0。定义多个变量时,用逗号隔开:int n,a,ans1,ans2;

初始化是给变量赋初始值。全局变量(定义在main外)会自动初始化为 0,而局部变量(定义在main内)需要手动初始化,比如:

cpp

int main(){
    int ans1 = 0; // 必须手动初始化
    int ans2 = 0;
    // ...其他代码
}

如果局部变量不初始化,它的值是随机的(比如之前内存中的残留值),会导致统计错误!这是初学者最容易踩的坑之一,一定要注意~

4.2 输入输出:程序与用户的交互

程序需要和用户交互,cincout就是交互的工具:

  • cin>>变量名:从输入设备(键盘)读取数据到变量;
  • cout<<变量名:把变量的值输出到屏幕。

使用时要注意:

  • 读取多个数据时,cin可以连写:cin>>n>>a(但这道题需要先读 n,再循环读 a);
  • 输出多个内容时,cout可以连写,用<<连接:cout<<ans1<<" "<<ans2
  • 输出空格时,用" "表示(双引号包裹空格)。

输入输出就像程序的 “嘴巴和耳朵”,让程序能接收指令并展示结果。

4.3 循环结构:重复执行的利器

这道题用了while(n--)循环,它的作用是重复执行n次操作。while循环的基本格式是:

cpp

while(条件){
    // 循环体:要重复执行的代码
}

当条件为真(非 0)时,执行循环体;执行完后再次判断条件,直到条件为假(0)时停止。

n--是 “后置递减”,先使用n的当前值判断条件,再把n减 1。比如n=3时:

for(int i=0;i<n;i++){
    cin>>a;
    if(a%2!=0)ans1++;
    else ans2++;
}

4.4 分支判断:if-else 语句

判断奇偶数的核心是if-else语句,它的作用是 “根据条件选择不同的操作”,基本格式是:

if(条件){
    // 条件为真时执行的代码
}else{
    // 条件为假时执行的代码
}

4.5 计数器:累加统计

计数器是统计类问题的核心工具,ans1ans2就是两个计数器。计数器的使用步骤是:

五、易错点分析:避开这些 “坑”

虽然这道题简单,但初学者很容易在细节上出错。咱们盘点几个常见的易错点,帮你避开陷阱~

5.1 变量未初始化

错误示例

int main(){
    int n,a,ans1,ans2; // 错误:局部变量未初始化
    cin>>n;
    while(n--){
        cin>>a;
        if(a%2!=0)ans1++;
        else ans2++;
    }
    cout<<ans1<<" "<<ans2;
}
int ans1 = 0, ans2 = 0; // 正确:手动初始化为0

5.2 奇偶数判断条件错误

错误示例

if(a%2==1)ans1++; // 错误:忽略了负奇数的情况
else ans2++;
if(a%2!=0)ans1++; // 正确:所有奇数都满足
else ans2++;

5.3 循环次数错误

错误示例

while(n){ // 错误:循环条件应为n--
    cin>>a;
    // ...判断代码
    n--;
}

5.4 输出格式错误

错误示例 1:输出时忘记加空格

cout<<ans1<<ans2; // 错误:输出结果连在一起,如“21”
cout<<"奇数:"<<ans1<<" 偶数:"<<ans2; // 错误:包含多余文字
cout<<ans1<<" "<<ans2; // 正确格式

5.5 数据类型选择错误

虽然这道题的输入范围不会导致问题,但初学者可能会疑惑:为什么用int类型?int类型能存储的整数范围是 - 2147483648 到 2147483647,足够存储题目中的输入数据(GESP 一级题的输入通常在这个范围内)。如果遇到更大的数,可能需要用long long类型,但这道题用int完全足够。

六、代码优化与拓展:让程序更完善

这道题的代码虽然简单,但可以通过一些优化让它更规范、更高效。同时,我们也可以拓展思路,解决更复杂的问题~

6.1 变量命名更清晰

示例代码用ans1ans2作为计数器,虽然简洁,但可以起更有意义的名字,让代码更容易理解:

int odd_count = 0; // 奇数计数器(odd表示奇数)
int even_count = 0; // 偶数计数器(even表示偶数)

6.2 用 for 循环替代 while 循环

除了while(n--),也可以用for循环处理,逻辑更清晰:

cin>>n;
for(int i=0;i<n;i++){ // i从0到n-1,共循环n次
    cin>>a;
    if(a%2!=0)odd_count++;
    else even_count++;
}

6.3 处理负数的特殊情况

题目中没有明确说明输入是否包含负数,但好的程序应该能处理负数。如 4.5 节所述,用a%2!=0判断奇数可以正确处理负数,比如:

6.4 拓展练习:计算奇偶数的和

学会了统计奇偶数的数量,我们可以尝试更复杂的问题:计算所有奇数的和与所有偶数的和。

#include<bits/stdc++.h>
using namespace std;
int n,a,sum_odd,sum_even; // 累加器
int main(){
    cin>>n;
    while(n--){
        cin>>a;
        if(a%2!=0)sum_odd += a; // 奇数累加
        else sum_even += a; // 偶数累加
    }
    cout<<sum_odd<<" "<<sum_even;
    return 0;
}

六、PPT 展示建议:让讲解更清晰

如果用这篇内容制作 PPT,建议按以下结构分页,突出重点,适合课堂讲解或自我复习:

七、写在最后:从简单题中积累编程思维

“奇数和偶数” 这道题虽然简单,但蕴含了编程的核心思维:把复杂问题拆解为简单步骤,用变量存储数据,用循环处理重复操作,用判断实现分支逻辑,用计数器统计结果。这些思维不仅适用于这道题,更适用于未来更复杂的编程问题。

  • 第一次判断:条件是 3(真),执行循环体,然后 n 变成 2;
  • 第二次判断:条件是 2(真),执行循环体,然后 n 变成 1;
  • 第三次判断:条件是 1(真),执行循环体,然后 n 变成 0;
  • 第四次判断:条件是 0(假),循环结束。

  • 如果条件为真(余数是 1),说明是奇数,执行ans1++
  • 如果条件为假(余数是 0),说明是偶数,执行ans2++

  • 初始化计数器为 0;
  • 每次遇到符合条件的数据,计数器加 1(ans++);
  • 所有数据处理完后,计数器的值就是统计结果。

  • -3%2 = -1-1 != 0→奇数,正确;
  • -4%2 = 0→偶数,正确。

  • 奇数和:1+3=4
  • 偶数和:2
  • 输出:4 2

  • 封面页

    • 标题:洛谷 B4063 奇数和偶数
    • 副标题:GESP 一级编程题解析
    • 背景图:数字或代码相关图片(如 0 和 1 组成的背景)
  • 题目介绍页

    • 用简洁语言描述题目要求(输入 n 个整数,统计奇偶数数量)
    • 列出输入输出格式(表格形式)
    • 展示 1-2 个示例(输入→分析→输出)
  • 核心思路页

    • 用流程图展示 “读取 n→循环读 a→判断奇偶数→统计计数→输出结果” 的步骤
    • 标注每个步骤的作用,用箭头连接流程
  • 奇偶数判断原理页

    • 简单复习奇偶数的数学定义
    • 重点讲解判断方法:a%2!=0是奇数,否则是偶数
    • 举例说明(3 是奇数,4 是偶数,0 是偶数)
  • 代码框架页

    • 展示完整代码,用不同颜色标出核心部分(变量定义、循环、判断、输出)
    • 简要说明代码结构:输入→循环→判断→输出
  • 代码解析页(分 2-3 页):

    • 逐行解释代码含义,重点讲解变量作用
    • 单独讲解 while 循环的执行过程(用 n=3 举例)
    • 单独讲解 if-else 判断逻辑(用 a=1、a=2 举例)
  • 执行过程演示页

    • 以示例输入为例,用表格展示每一步的变量变化:
      循环次数 n 的值 a 的值 ans1 ans2
      初始 3 0 0
      第一次 3→2 1 1 0
      第二次 2→1 2 1 1
      第三次 1→0 3 2 1
    • 用动画或颜色标注变化过程
  • 易错点分析页

    • 用 “错误代码 + 正确代码” 的对比表格,列出常见错误:
      错误类型 错误代码示例 正确代码示例
      变量未初始化 int ans1; int ans1 = 0;
      判断条件错误 if(a%2==1) if(a%2!=0)
      输出格式错误 cout<<ans1<<ans2; cout<<ans1<<" "<<ans2;
    • 标注错误原因和后果
  • 核心知识点总结页

    • 用 bullet point 列出关键知识点:
      • 变量定义与初始化的重要性
      • while 循环的使用(控制循环次数)
      • if-else 分支判断(奇偶数判断)
      • 计数器的累加统计方法
      • 输入输出格式规范
  • 拓展练习页

    • 提出拓展问题(如计算奇偶数的和)
    • 展示拓展题的思路和代码框架
    • 鼓励尝试并对比与本题的异同
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐