for循环 - while循环 - 习题解析

1389. 数据分析

问题描述

某军事单位采用特殊加密方法传递信息。传递一个整数n(10位以内),其长度代表第一个数字信息,将n的偶数位相加得到第二个数字信息。要求编写程序从n中获取这两个数字信息。

解题思路
  1. 读取输入:接收一个整数n。
  2. 计算位数:初始化一个计数器,循环除以10直到n变为0,得到位数。
  3. 计算偶数位之和:在计算位数的同时,判断每一位是否为偶数,如果是则累加。
  4. 输出结果:输出位数和偶数位之和。
代码实现
cpp 复制代码
#include <iostream>
using namespace std;

int main() {
    long long n;
    cin >> n;
    
    int digits = 0;
    int sum = 0;
    
    while (n > 0) {
        int digit = n % 10;
        digits++;
        
        if (digit % 2 == 0) {
            sum += digit;
        }
        
        n /= 10;
    }
    
    cout << digits << " " << sum << endl;
    
    return 0;
}
代码解析
  • 使用long long类型存储输入的n,因为n可能高达10^9。
  • 初始化digits变量记录位数,sum变量记录偶数位之和。
  • 使用while循环处理n的每一位:
    • n % 10获取最后一位数字。
    • digits++计数位数。
    • 判断该位是否为偶数,是则加到sum中。
    • n /= 10去掉最后一位。
  • 循环结束后,digits存储位数,sum存储偶数位之和。
  • 最后按要求格式输出结果。

1750. 有0的数

问题描述

求出1到n(n≤999)之间含有数字0的数的个数。

解题思路
  1. 遍历数字:从1遍历到n。
  2. 分解每个数:对于每个数,分解成个位、十位和百位。
  3. 检查每一位:检查每一位是否为0。
  4. 计数:如果一个数的任何一位是0,则计数器加1。
代码实现
cpp 复制代码
#include <iostream>
using namespace std;

int main() {
    int n;
    cin >> n;
    
    int count = 0;
    for (int i = 1; i <= n; i++) {
        int num = i;
        bool hasZero = false;
        
        while (num > 0) {
            if (num % 10 == 0) {
                hasZero = true;//存在0位
                break;
            }
            num /= 10;
        }
        
        if (hasZero) {
            count++;
        }
    }
    
    cout << count << endl;
    return 0;
}
代码解析
  • 读取输入n。
  • 使用for循环遍历1到n的所有数。
  • 对于每个数i:
    • 将i赋值给临时变量num
    • 使用while循环检查num的每一位:
      • 如果当前位(num % 10)等于0,设置hasZero为true并跳出循环。
      • 否则,将num除以10,检查下一位。
    • 如果hasZero为true,增加计数器count
  • 循环结束后,输出count,即包含0的数的个数。
  • 这种方法的时间复杂度仍然是O(n log n),因为对每个数都要检查其每一位。
  • 这个实现没有使用单独的函数,而是将所有逻辑都放在main函数中,符合不使用函数的要求。
  • 对于n≤999的情况,这种方法是足够高效的。如果n的范围更大,可能需要考虑更优化的算法。

1962. 数值计算

问题描述

给出一个不多于5位的非负整数(非0结尾),要求:

  1. 求出它是几位数
  2. 分别输出每一位数字
  3. 按逆序输出各位数字
解题思路
  1. 计算位数:使用循环除以10,直到商为0,计数得到位数。
  2. 输出每一位数字:利用整数除法和取模运算,从高位到低位输出每一位。
  3. 逆序输出:直接使用取模运算从低位到高位输出。
代码实现
cpp 复制代码
#include <iostream>
#include <cmath>
using namespace std;

int main() {
    int num, originalNum; // 声明变量存储输入的数字和原始数字
    cin >> num; // 读取输入的数字
    originalNum = num; // 保存原始数字,因为num会在后续操作中被修改

    // 计算位数
    int count = 0; // 初始化计数器
    int temp = num; // 临时变量,用于计算位数
    while (temp > 0) { // 当temp大于0时继续循环
        temp /= 10; // 每次除以10
        count++; // 位数加1
    }

    // 输出位数
    cout << count << endl; // 输出计算得到的位数

    // 输出每一位数字
    int divisor = pow(10, count - 1); // 计算最高位的除数
    while (divisor > 0) { // 当除数大于0时继续循环
        cout << num / divisor; // 输出当前位的数字
        if (divisor > 1) cout << " "; // 如果不是最后一位,输出空格
        num %= divisor; // 更新num为余数
        divisor /= 10; // 除数除以10,准备处理下一位
    }
    cout << endl; // 输出换行

    // 按逆序输出
    while (originalNum > 0) { // 当原始数字大于0时继续循环
        cout << originalNum % 10; // 输出最后一位
        originalNum /= 10; // 去掉最后一位
    }
    cout << endl; // 输出换行

    return 0; // 程序结束
}
代码解析
  • 代码中每一行都添加了注释,解释了该行的作用。
  • 这种实现方法不使用数组,而是通过数学运算来处理每一位数字。
  • 时间复杂度是O(log n),其中n是输入的数字,因为我们需要处理每一位数字。
  • 空间复杂度是O(1),因为只使用了常数级的额外空间。
  • 这个解决方案适用于不超过5位的正整数,完全符合题目要求。

1121. "倒"数

问题描述

输入一个正整数N(0<N<2147483647),将这个数倒着合成一个新数后输出。注意:不保留前导零。

解题思路
  1. 读取输入:读取给定的正整数N。
  2. 逐位处理:从个位开始,逐位提取数字。
  3. 构建新数:将提取的数字按相反顺序构建成新的数。
  4. 输出结果:输出构建的新数。
代码实现
cpp 复制代码
#include <iostream>
using namespace std;

int main() {
    int N; // 声明变量存储输入的正整数
    cin >> N; // 读取输入的数字

    int reversedNum = 0; // 用于存储倒序后的新数

    while (N > 0) { // 当N大于0时继续循环
        int digit = N % 10; // 获取N的最后一位数字
        reversedNum = reversedNum * 10 + digit; // 将digit添加到reversedNum的末尾
        N /= 10; // 去掉N的最后一位
    }

    cout << reversedNum << endl; // 输出倒序后的新数

    return 0; // 程序结束
}
代码解析
  • int N;:声明变量N来存储输入的正整数。

  • cin >> N;:从标准输入读取正整数N。

  • int reversedNum = 0;:初始化reversedNum为0,用于存储倒序后的新数。

  • while (N > 0):当N大于0时,继续循环处理每一位数字。

  • int digit = N % 10;:通过取模运算获取N的最后一位数字。

  • reversedNum = reversedNum * 10 + digit;:将新的数字添加到reversedNum的末尾。

  • N /= 10;:去掉N的最后一位数字。

  • cout << reversedNum << endl;:输出倒序后的新数。

  • 这种方法的时间复杂度是O(log N),其中N是输入的数字,因为我们需要处理每一位数字。

  • 空间复杂度是O(1),因为我们只使用了常数级的额外空间。

  • 这个解决方案自动处理了前导零的问题,因为在构建新数时,前导零自然被忽略了。

  • 该实现方法适用于题目给定范围内的所有正整数(0<N<2147483647)。

1469. 数的统计

问题描述

计算在区间1到n的所有整数中,数字x(0≤x≤9)共出现了多少次。

解题思路
  1. 读取输入:读取n和x的值。
  2. 遍历区间:从1遍历到n。
  3. 统计出现次数
    • 对每个数,分解其各个位。
    • 检查每一位是否等于x。
    • 如果等于,计数器加1。
  4. 输出结果:输出最终的计数。
代码实现
cpp 复制代码
#include <iostream>
using namespace std;

int main() {
    int n, x; // 声明变量n和x
    cin >> n >> x; // 读取输入的n和x

    int count = 0; // 初始化计数器

    // 遍历从1到n的每个数
    for (int i = 1; i <= n; i++) {
        int current = i; // 当前处理的数
        
        // 分解current的每一位并检查
        while (current > 0) {
            if (current % 10 == x) { // 如果当前位等于x
                count++; // 计数器加1
            }
            current /= 10; // 去掉最后一位
        }
    }

    cout << count << endl; // 输出x出现的次数

    return 0; // 程序结束
}
代码解析
  • int n, x;:声明变量n和x,分别表示区间上限和要统计的数字。

  • cin >> n >> x;:从标准输入读取n和x的值。

  • int count = 0;:初始化计数器count为0。

  • for (int i = 1; i <= n; i++):遍历从1到n的每个数。

  • int current = i;:将当前处理的数赋值给current。

  • while (current > 0):循环处理current的每一位。

  • if (current % 10 == x):检查current的最后一位是否等于x。

  • count++;:如果等于x,计数器加1。

  • current /= 10;:去掉current的最后一位。

  • cout << count << endl;:输出最终的计数结果。

  • 时间复杂度:O(n log n),其中n是输入的上限值。对每个数都需要检查其每一位。

  • 空间复杂度:O(1),只使用了常数级的额外空间。

  • 这个解决方案适用于题目给定的所有输入范围(n是int范围内的整数)。

  • 该方法通过逐个检查每个数的每一位来统计x的出现次数,确保了准确性。

1511. 数字之和为13的整数

问题描述

求出1到n范围内的整数中,数字之和为13的数的个数。n不超过10000000。

解题思路
  1. 遍历范围:从1遍历到n。
  2. 计算数字和:对每个数,计算其各位数字之和。
  3. 统计符合条件的数:如果数字和等于13,计数器加1。
  4. 输出结果:输出最终的计数。
代码实现
cpp 复制代码
#include <iostream>
using namespace std;

int main() {
    int n; // 声明变量n
    cin >> n; // 读取输入的n

    int count = 0; // 初始化计数器

    // 遍历从1到n的每个数
    for (int i = 1; i <= n; i++) {
        int sum = 0; // 用于存储当前数字的各位之和
        int current = i; // 当前处理的数
        
        // 计算current的各位数字之和
        while (current > 0) {
            sum += current % 10; // 加上最后一位
            current /= 10; // 去掉最后一位
        }

        // 如果和为13,计数器加1
        if (sum == 13) {
            count++;
        }
    }

    cout << count << endl; // 输出符合条件的数的个数

    return 0; // 程序结束
}
代码解析
  • int n;:声明变量n,用于存储输入的范围上限。

  • cin >> n;:从标准输入读取n的值。

  • int count = 0;:初始化计数器count为0。

  • for (int i = 1; i <= n; i++):遍历从1到n的每个数。

  • int sum = 0;:初始化sum为0,用于存储当前数字的各位之和。

  • int current = i;:将当前处理的数赋值给current。

  • while (current > 0):循环处理current的每一位。

  • sum += current % 10;:将current的最后一位加到sum上。

  • current /= 10;:去掉current的最后一位。

  • if (sum == 13):检查sum是否等于13。

  • count++;:如果sum等于13,计数器加1。

  • cout << count << endl;:输出最终的计数结果。

  • 时间复杂度:O(n log n),其中n是输入的上限值。对每个数都需要计算其各位之和。

  • 空间复杂度:O(1),只使用了常数级的额外空间。

  • 这个解决方案适用于题目给定的所有输入范围(n≤10000000)。

  • 该方法通过逐个检查每个数的各位之和来统计符合条件的数的个数,确保了准确性。

  • 对于较大的n值,这种方法可能会比较耗时,但在给定的范围内仍然是可行的。

1149. 回文数个数

问题描述

给定一个正整数n(1≤n≤10000),求出1到n之间(包括1和n)的回文数的个数。

解题思路
  1. 遍历范围:从1遍历到n。
  2. 判断回文:对每个数,判断是否为回文数。
  3. 统计回文数:如果是回文数,计数器加1。
  4. 输出结果:输出最终的计数。
代码实现
cpp 复制代码
#include <iostream>
using namespace std;

int main() {
    int n; // 声明变量n
    cin >> n; // 读取输入的n

    int count = 0; // 初始化计数器

    // 遍历从1到n的每个数
    for (int i = 1; i <= n; i++) {
        int original = i; // 保存原始数字
        int reversed = 0; // 用于存储反转后的数字
        int temp = i; // 临时变量,用于反转过程

        // 反转数字
        while (temp > 0) {
            reversed = reversed * 10 + temp % 10;
            temp /= 10;
        }

        // 判断是否为回文数
        if (original == reversed) {
            count++;
        }
    }

    cout << count << endl; // 输出回文数的个数

    return 0; // 程序结束
}
代码解析
  • int n;:声明变量n,用于存储输入的范围上限。

  • cin >> n;:从标准输入读取n的值。

  • int count = 0;:初始化计数器count为0。

  • for (int i = 1; i <= n; i++):遍历从1到n的每个数。

  • int original = i;:保存原始数字。

  • int reversed = 0;:用于存储反转后的数字。

  • int temp = i;:临时变量,用于反转过程。

  • while (temp > 0):循环反转数字。

  • reversed = reversed * 10 + temp % 10;:构建反转后的数字。

  • temp /= 10;:去掉temp的最后一位。

  • if (original == reversed):判断原数字是否等于反转后的数字。

  • count++;:如果是回文数,计数器加1。

  • cout << count << endl;:输出最终的计数结果。

  • 时间复杂度:O(n log n),其中n是输入的上限值。对每个数都需要进行反转操作。

  • 空间复杂度:O(1),只使用了常数级的额外空间。

  • 这个解决方案适用于题目给定的所有输入范围(1≤n≤10000)。

  • 该方法通过反转每个数并与原数比较来判断是否为回文数,确保了准确性。

  • 对于给定的范围(最大10000),这种方法是高效且可行的。

1846. 阿尔法乘积

问题描述

计算一个整数的阿尔法乘积。阿尔法乘积的计算规则是:

  1. 如果是个位数,阿尔法乘积就是它本身。
  2. 否则,计算各位非0数字的乘积,然后重复此过程直到得到一个个位数。
解题思路
  1. 循环计算:使用循环代替递归,重复计算直到结果为个位数。
  2. 乘积计算:在每次循环中计算各位非0数字的乘积。
  3. 结果判断:当结果小于10时结束循环。
代码实现
cpp 复制代码
#include <iostream>
using namespace std;

int main() {
    int n; // 声明变量n
    cin >> n; // 读取输入的整数

    while (n >= 10) { // 当n不是个位数时继续循环
        int product = 1; // 用于存储各位非0数字的乘积
        int temp = n; // 临时变量,用于分解数字

        // 计算各位非0数字的乘积
        while (temp > 0) {
            int digit = temp % 10; // 获取最后一位数字
            if (digit != 0) {
                product *= digit; // 如果不是0,则乘到product中
            }
            temp /= 10; // 去掉最后一位
        }

        n = product; // 更新n为新的乘积
    }

    cout << n << endl; // 输出最终结果

    return 0; // 程序结束
}
代码解析
  • int n;:声明变量n,用于存储输入的整数和中间结果。

  • cin >> n;:从标准输入读取n的值。

  • while (n >= 10):外层循环,当n不是个位数时继续计算。

  • int product = 1;:初始化product为1,用于存储各位非0数字的乘积。

  • int temp = n;:临时变量temp,用于分解数字。

  • while (temp > 0):内层循环,处理temp的每一位数字。

  • int digit = temp % 10;:获取temp的最后一位数字。

  • if (digit != 0) { product *= digit; }:如果digit不为0,则乘到product中。

  • temp /= 10;:去掉temp的最后一位。

  • n = product;:更新n为新的乘积。

  • cout << n << endl;:输出最终结果。

  • 时间复杂度:O(log n * log n),其中n是输入的整数。外层循环最多执行log n次,每次内层循环也最多执行log n次。

  • 空间复杂度:O(1),只使用了常数级的额外空间。

  • 这个解决方案适用于题目给定的所有输入范围(int范围内的正整数)。

  • 该方法通过循环实现了阿尔法乘积的计算,避免了使用递归和函数调用,符合题目要求。

相关推荐
天秀信息学奥赛1 个月前
T3-加密通信题解
算法·csp-j·bcsp-x模拟题·t3-加密通信
ya888g1 个月前
信息学奥赛初赛天天练-20-完善程序-vector数组参数引用传递、二分中值与二分边界应用的深度解析
数据结构·c++·算法·csp-j·信息学奥赛·初赛
cqbzcyy8 个月前
2023CSP-J题解
算法·csp-j
爱编程的小芒果9 个月前
CSDN里的常用网址(2)
c++·算法·csp-j·编程蠢事·小时候的蠢代码