编程之美2.4——“1”的数目

题目描述:给定一个正整数N,写出1到N(包含N)的所有正整数,然后数一下其中出现的所有N的个数。
举个例子,假设你输入的是11,则1到11的所有正整数为:
1,2,3,4,5,6,7,8,9,10,11
其中1出现了四次(1,10,11),请编写一个程序完成这个任务。
最暴力的解法这里不用说,因为如果面试的话肯定会死,微软的面试要是写出这种代码就能活下来也太容易了。
当我第一次看到这道题时,我先自己想了一下。不过没想出来,后来看了答案发现是我自己的思路有问题。我的思路是由最高位开始算,可解法偏偏是由最低位开始算。后来仔细想一下,从最低位开始算的这种思路实在是精妙。

问题分析

暴力循环不行,所以换个角度来看。可以把问题这样分解,从1到N的所有数字中,各位上有多少个1,十位上有多少个1,百位上有多个1.。。。。。。。
对于每一个位数字,可以分类讨论

1:该位数字大于1
2:该位数字等于1
3:该位数字等于0

之所以要分为3种情况,是因为“1”是一个特殊数字。

对于213。

如果十位数字是1,则十位上1的个数不仅和高位数字2有关,也和低位数字3有关——110-119,210-213
如果十位数字是2(大于1)即223,则此时十位上出现1的次数只与高位数字有关——110-119,210-219。
如果十位数字是0(小于1)即203,则此时十位上出现1的次数也只与高位数字有关——110-119
上述就是问题的关键

下面是一个简单的实现:

/*
get the number of 1
*/
#include <iostream>
#include <string>
using namespace std;
int calc(int n){
    auto count=0;
    int factor=1;
    int lowerNum=0;
    int currentNum=0;
    int highNum=0;

    while(n/factor!=0){
        lowerNum=n-(n/factor)*factor;
        currentNum=(n/factor)%10;
        highNum=n/(factor*10);

        switch(currentNum){
            case 0:
            count+=highNum*factor;
            break;
            case 1:
            count+=highNum*factor+lowerNum+1;
            break;
            case 2:
            count+=(highNum+1)*factor;
            break;
        }
        factor*=10;
    }
    return count;
}
int main(int argc,char **argv){
    int num=0;
    cout<<"cin num: "<<endl;
    cin>>num;
    int count=calc(num);
    cout<<count<<endl;
    return 0;
}

PS:这道题真是体现了编程的美,一个优秀的程序员就如一个设计师

以上

本实验旨在帮助学生掌握 Python 元组的基本概念和操作,过实际操作加深对元组的 理解,并提高解决实际问题的能力。 1. 理解和掌握元组的定义和初始化方法。 2. 熟悉元组的各种操作,包括访问、拼接、切片、解压和遍历等。 3. 能够应用元组解决实际问题,例如统计竞赛参与者的信息。 三、实验任务及原理 任务要求: 假设有 20 名同学参加了编程竞赛,每位同学的信息包括:学号、姓名、完成题⽬数、 总⽤时。请按照如下要求完成: (1)输⼊每位同学的信息,使⽤元组存储。 (2)根据完成题⽬数进⾏排序,并显示前 3 名同学的信息(完成题⽬数最多的排在前 ⾯,若题⽬数相同,则总⽤时最少的排在前⾯)。显示格式如下: 学号 姓名 完成题⽬数 总⽤时 22208015501 张三 10 90m23s 22208015502 李三 10 100m33s 22208015503 王三 9 98m14s 计算所有⼈的完成题⽬的平均数并显示 (4)计算每个⼈的完成的题⽬平均时间并排序显示 学号 姓名 完成题⽬数 总⽤时 平均⽤时 22208015501 张三 10 90m23s 9m2s 22208015502 李三 10 100m33s 10m3s 22208015503 王三 9 98m14s 10m55s ……. 理论知识: (1)元组的定义 在 Python 中,元组(tuple)是⼀种有序的、不可变的数据类型。它可以包含任意类型 的元素,包括数字、字符串、列表等。元组使⽤⼩括号 () 来创建,并且元组中的元素可以 过索引访问。与列表(list)不同,元组⼀旦创建就不能被修改。Python 是⼀种动态类型 语⾔,在定义变量时不需要明确指定变量的类型,Python 会根据赋给变量的值来⾃动确定 其类型。 创建元组的⽅法: 1.1 包含任意元素 numbers = (1, 2, 3, 4, 5) words = ("apple", "banana", "cherry") mixed_list = (1, "hello", 3.14, True) 1.2 使⽤ tuple()构造函数 numbers = tuple(range(1, 6)) 1.3 创建只包含 1 个元素的元组 single_element_tuple = (42,) 1.4 元组的嵌套 元组的嵌套指的是在⼀个元组中包含其他元组或不同类型的数据结构。使⽤嵌套可以创 建更复杂的数据结构,其中包含多个层次的元组结构。 nested_tuple = (1, 2, (3, 4), ("a", "b", "c")) (2)元组的操作 元组的操作包括:访问、添加、删除、修改、拼接、重复、切⽚、解压、遍历。 2.1 访问 可以使⽤索引来访问元组中的元素。需要注意的是,索引必须是整数类型,并且不能超 出元组的范围,否则会引发 IndexError 错误。 my_tuple = (1, 2, 3, 4, 5) print(my_tuple[0]) print(my_tuple[-1]) 2.3 添加、删除、修改 在 Python 中,元组是不可变的数据类型,这意味着⼀旦创建,就不能添加、修改或删 除元素。元组的元素是固定的,不能被更改。 如果需要添加元素,可以创建⼀个新的元组,将原来的元组与新元素合并。 my_tuple = (1, 2, 3) new_tuple = my_tuple + (4,) 如果需要删除元素,只能创建⼀个新的元组,将不需要的元素排除在外。 my_tuple = (1, 2, 3, 4, 5) # 删除 my_tuple[3] new_tuple = my_tuple[:3] + my_tuple[4:] print(my_tuple) print(new_tuple) 如果需要修改元组中的某个元素,只能创建⼀个新的元组来替代原来的元组。 my_tuple = (1, 2, 3, 4, 5) # my_tuple[3] = -4 错误! new_tuple = my_tuple[:3] + (-4,) + my_tuple[4:] print(my_tuple) print(new_tuple) 2.4 拼接 元组的拼接可以过 + 运算符来实现。当使⽤ + 运算符连接两个元组时,会创建⼀ 个新的元组,包含原始元组中的所有元素。 tuple1 = (1, 2, 3) tuple2 = (4, 5, 6) result_tuple = tuple1 + tuple2 print(result_tuple) print(new_tuple) 2.5 重复 可以使⽤乘法运算符 * 来实现元组的重复。过将⼀个元组与⼀个整数相乘,可以创 建⼀个新的元组,其中包含原始元组重复指定次数的内容。 my_tuple = (1, 2, 3) # 创建⼀个新的元组,并赋值给原始元组变量 my_tuple = my_tuple * 3 print(my_tuple) 2.6 切⽚ 过指定起始索引、结束索引和步⻓来获取元组的⼦集。切⽚操作返回⼀个新的元组, ⽽原始元组保持不变。 my_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9) # 获取索引 1 到索引 4 之间的元素(不包括索引 4) subset1 = my_tuple[1:4] print(subset1) # 获取从索引 2 开始到结束的元素 subset2 = my_tuple[2:] print(subset2) # 获取从开始到索引 6(不包括索引 6)的元素,步⻓为 2 subset3 = my_tuple[:6:2] print(subset3) # 获取整个元组的逆序 reverse_tuple = my_tuple[::-1] print(reverse_tuple) # 从索引 5 到 1(不包括索引 1)逆序,步⻓为 2 reverse_tuple = my_tuple[5:1:-2] print(reverse_tuple) 2.7 解压 元组的解压指的是将元组中的元素分别赋值给多个变量的过程。当⼀个元组中包含多个 元素,⽽且希望将这些元素分别赋值给多个变量时,可以使⽤解压操作。 my_tuple = (1, 2, 3) a, b, c = my_tuple print(a) print(b) print(c) 元组的解压⾮常有⽤,特别是在函数返回多个值时。例如,可以将⼀个函数返回的多个 值直接解压到多个变量中 def get_coordinates(): return (10, 20, 30) x, y, z = get_coordinates() print("x =", x) print("y =", y) print("z =", z) 可以使⽤星号 * 来捕获多余的元素,将其作为⼀个列表赋值给⼀个变量。 my_tuple = (1, 2, 3, 4, 5) a, b, *rest = my_tuple print(a) print(b) print(rest) # 输出: [3, 4, 5] 2.8 遍历 使⽤ for 遍历元组 my_tuple = (1, 2, 3, 4, 5) for element in my_tuple: print(element) 使⽤索引遍历元组 my_tuple = (1, 2, 3, 4, 5) for i in range(len(my_tuple)): print(my_tuple[i]) 同时遍历索引和元素 my_tuple = (1, 2, 3, 4, 5) for index, element in enumerate(my_tuple): print(f"Index {index}: {element}") 四、实验环境 (1)PyCharm 社区版 (2)Anaconda(Python 3.10 以上) 五、实验预习任务 (1)复习元组的定义和基本操作。 (2)查阅元组的切片、解压和拼接方法的使用。 (3)尝试编写简单的元组操作代码。 六、实验过程(实验方案) (1)收集学生信息 使用循环和 input()`函数逐个输入 20 名同学的个人信息(学号、姓名、 完成题目数、总用时)。 将每位同学信息存储为元组,放入一个列表中。 (2)数据处理和统计 遍历列表,按完成题目数排序(题目数相同则按总用时排序),计算所有同学完成题目的平均数。 计算每位同学的平均用时(总用时除以题目数),并按平均用时排序。 (3)输出结果 根据要求和使用 print 函数和 f-字符串对数据格式化输出 七、实验课后任务 (1)为代码添加详细注释。 (2)尝试使用不同的列表操作方法完成相同的统计任务。 (3)将项目源码提交到指定平台。 八、实验考核 (1)列表定义和操作的正确性。 (2)数据处理和统计的准确性。 (3)代码的可读性和可维护性。 (4)实验报告的完整性和清晰度。 九、实验资源 智慧平台中课件:06 元组.pdf
最新发布
04-03
好的,下面是对这个实验内容的一个总结和解答: ### 实验概述 本次实验的目标是帮助学生掌握 **Python 元组** 的基本概念及其操作,并过具体的编程实践加深对元组的理解。我们将围绕“竞赛参与者信息管理”这一场景展开实验任务。 --- ### 核心知识点回顾 #### 1. **元组的定义** - 元组是一种有序且不可变的数据结构。 - 使用小括号 `()` 表示,例如 `(1, 2, 3)` 或者利用构造函数 `tuple([iterable])` 创建。 - 特点:一旦创建无法修改(如添加、删除或替换元素),因此适用于存储固定数据集合的情况。 #### 2. **元组的基本操作** | 操作名称 | 描述 | |--------------|-------------------------------------------------------------| | 访问 | 支持正向索引 `[i]` 和负向索引 `[-i]` | | 拼接 | 可以使用 `+` 符号将两个元组合并 | | 切片 | 提取部分元素,语法为 `[start:end:step]` | | 解压 | 把元组中的值分配给多个变量 | | 遍历 | 使用 `for-in` 循环逐一访问 | #### 3. **应用场景分析** 在本实验中,我们用元组表示学生的个人参赛记录 `{学号, 姓名, 完成题数, 总用时}`。由于每位选手的成绩不会变化,适合采用这种不可变容器保存。 --- ### 实现步骤详解 以下是根据实验任务的具体实现思路: #### (1)输入数据 ```python students = [] # 存储所有学生的元组信息 for _ in range(20): # 输入20名同学的信息 student_id = input("请输入学号:") name = input("请输入姓名:") solved_problems = int(input("请输入完成题目数:")) total_time = input("请输入总用时(分钟秒格式,如90m23s):") students.append((student_id, name, solved_problems, total_time)) # 构造元组存入列表 ``` #### (2)排序与统计 ##### a) 排序规则 先按完成题目数降序排列;若数目相同,则再依据总耗时升序决定顺序。 ```python from time import strptime # 时间解析工具 # 自定义比较函数 def sort_key(student_info): problems_solved = student_info[2] try: minutes, seconds = map(int, student_info[3].strip('ms').split('m')) total_seconds = minutes * 60 + seconds except ValueError: raise Exception(f"无效的时间格式 {student_info[3]}!") return (-problems_solved, total_seconds) sorted_students = sorted(students, key=sort_key) # 对学生进行排序 print("\n前3名成绩如下:") for idx, stu in enumerate(sorted_students[:3], start=1): print(f"{idx}. 学号:{stu[0]}, 姓名:{stu[1]}, 完成题数:{stu[2]}, 总用时:{stu[3]}") ``` ##### b) 平均完成题数 ```python total_problems = sum(s[2] for s in students) average_problems = total_problems / len(students) print(f"\n全体成员平均完成题数为{average_problems:.2f}道.") ``` ##### c) 平均每题所需时间 计算公式为:`(总用时 ÷ 完成题数)` 注意异常情况——某位未答题的学生需特殊处理(避免除零错误)。 ```python averages_with_details = [] for stu in students: if stu[2]: # 若已完成非零数量题目才继续... m_str, s_str = stu[3][:-1].split('m') avg_min_sec = divmod(float(m_str)*60 + float(s_str[:-1]), stu[2]) averages_with_details.append((*stu, f"{avg_min_sec[0]}m{s_int}s")) final_avg_sorted = sorted( averages_with_details, key=lambda t:t[-1], reverse=False) print('\n每人平均每题所花时间为:') for item in final_avg_sorted: fmt_result=f'{item[0]}-{item[1]} ({item[2]}题/{item[3]}总计)' fmt_result += ' -> '+str(item[-1]) print(fmt_result) ``` --- ### 示例输出效果 假设用户依次录入了若干条有效数据之后得到类似这样的展示结果: ``` 前3名成绩如下: 1. 学号:22208015501, 姓名:张三, 完成题数:10, 总用时:90m23s 2. 学号:22208015502, 姓名:李三, 完成题数:10, 总用时:100m33s 3. 学号:22208015503, 姓名:王三, 完成题数:9, 总用时:98m14s 全体成员平均完成题数为7.5道. 每人平均每题所花时间为: 22208015501-张三 (10题/90m23s总计) -> 9m2s 22208015502-李三 (10题/100m33s总计) -> 10m3s ... ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值