这类题的核心是对数字的每一位进行提取、判断、计算,不管是 "好数""幸运数字",还是 "数位和""奇偶位判断" 等,都可以套用以下模板,根据题目规则调整核心判断逻辑即可
数位操作类题目通用模板:初始化→遍历 / 处理输入→数位分解→核心规则判断→结果更新 / 输出,仅需定制 "核心规则判断" 部分;下面先来看2道核心例题,然后我们再进一步总结!!
目录
幸运数字
在一个古老的城镇里,有一座神秘的塔。传说如果你能解开塔的谜题,你就有机会获得神秘
的宝藏。但是,这座塔的谜题非常难以解开。你需要找到一个幸运数字才能打开谜题。
给你一个由 2×n 位数字组成的密码。如果这个密码是幸运数字,那么它满足以下条件:
如果将密码分成前半部分和后半部分 ,每个数字都与后半部分的某个数字对应 ,并且前半部
分的每个数字都严格小于对应的后半部分的数字 ,或者前半部分的每个数字都严格大于对应
的后半部分的数字。 前半部分的每位数字的和是偶数。
请你编写一个程序,来判断这个密码是否是幸运数字。
输入格式
第一行包含一个整数 n ( 1≤n≤200 ),表示密码的长度。
第二行包含一个由 2n 个数字组成的字符串 ,表示密码。
输出格式
输出仅一行,如果这个密码是幸运数字,则输出 Y,否则输出 N。
样例输入
3
135246
样例输出
N
题目分析:
- 对应关系 :将密码分为前后两半(各
n位),每一位前半部分的数字都必须严格大于对应的后半部分数字,或者每一位都严格小于对应的后半部分数字。- 和的奇偶性:前半部分所有数字的和必须是偶数。
法一:
python
n=int(input())#整数n表示密码的长度
mima=input().strip()#数字字符串
a,b=mima[:n],mima[n:]#分割前半部分和后半部分
standard1=all(c1>c2 for c1,c2 in zip(a,b))
standard2=all(c1<c2 for c1,c2 in zip(a,b))
if not(standard1 or standard2):
print("N")
else:
total=sum(int(c)for c in a)
print("Y"if total%2==0 else"N") #根据题目计算前半部分数字的和看是否为偶数
zip(a, b):把前后两半的数字 "配对"
zip()函数的作用是将两个可迭代对象(这里是字符串a和b)按位置一一配对,返回一个包含元组的迭代器。
比如
a = "135",b = "246",zip(a, b)会生成:('1','2'), ('3','4'), ('5','6');比如
a = "642",b = "135",zip(a, b)会生成:('6','1'), ('4','3'), ('2','5')。
c1 > c2 for c1, c2 in zip(a, b):逐个判断配对关系这是生成器表达式 (极简版的循环),遍历
zip配对后的每一组元素,逐个判断:
c1 > c2:判断前半部分的当前位是否大于后半部分的对应位;
c1 < c2:判断前半部分的当前位是否小于后半部分的对应位。仍以
a="135", b="246"为例:
c1 > c2会依次得到:False, False, False;
c1 < c2会依次得到:True, True, True。
代码片段 作用 a, b = s[:n], s[n:]快速分割前后两半,替代循环索引,更简洁 all(c1 > c2 for ...)用 all()函数一键判断 "所有位都大于",替代手动循环,符合 Python 极简风格sum(int(c) for c in a)生成器表达式求和,比手动循环累加更高效,竞赛中更省时间 print("Y" if ... else "N")三元表达式替代 if-else,一行完成输出,精简代码行数
sum(int(c) for c in a)
(1)
for c in a:遍历前半部分的每一个字符
a是前半部分的数字字符串(比如"135"),for c in a会逐个取出字符串中的每个字符:
当
a = "135"时,依次取出'1'、'3'、'5';当
a = "246"时,依次取出'2'、'4'、'6'。(2)
int(c):把字符转成整数字符串类型的数字(如
'1')无法直接参与数学运算,int(c)会将字符转换为对应的整数:
int('1')→1,int('3')→3,int('5')→5;这一步是求和的前提,否则直接对字符求和会报错(比如
'1' + '3'会得到'13',而非4)。(3)
sum(...):对转换后的整数求和
sum()函数的作用是接收一个可迭代对象(这里是生成器表达式),并计算所有元素的总和:
sum(int(c) for c in "135")→1 + 3 + 5 = 9;
sum(int(c) for c in "246")→2 + 4 + 6 = 12。
法二:
python
n=int(input())#整数n表示密码的长度
mima=input().strip()#数字字符串
a=False#标志位
total=0#初始和为0
for i in range(n):#遍历前n个字符
if i==0:#对第一个字符特殊处理
total+=int(mima[i])#先累加第一个数字
# 试图通过第一个数字确定比较方向
if mima[i]<mima[i+n]:
a=False
else:
a=True
else:
if(not a and mima[i]<mima[i+n])or(a and mima[i]>mima[i+n]):
total+=int(mima[i])
else:
print("N")
exit()
if total%2==0:
print("Y")
else:
print("N")
- 如果
a=False(要求后续全<),则检查当前位是否<后半对应位;- 或者如果
a=True(要求后续全>),则检查当前位是否>后半对应位;- 只有满足其中一种情况,才累加当前数字;否则直接输出
N。
好数
一个整数如果按从低位到高位 的顺序,奇数位(个位、百位、万位 · · · )上的数字是奇数,
偶数位(十位、千位、十万位 · · · )上的数字是偶数,我们就称之为 "好数" 。
给定一个正整数 N ,请计算从 1 到 N 一共有多少个好数。
【输入格式】
一个整数 N 。
【输出格式】
一个整数代表答案。
【样例输入 1 】
24
1
【样例输出 1 】
7
1
【样例输入 2 】
2024
1
【样例输出 2 】
150
- 取余 10(num % 10) :获取当前数字的个位(最右边一位);
- 整数除法 10(num // 10):把数字 "右移一位",去掉已经获取的个位,原来的十位变成新的个位。
pythonnum = 56789 # 第一步:取个位 ge = num % 10 # 56789 % 10 = 9 num = num // 10 # 56789 // 10 = 5678 # 第二步:取十位(原数字的十位变成新的个位) shi = num % 10 # 5678 % 10 = 8 num = num // 10 # 5678 // 10 = 567 # 第三步:取百位 bai = num % 10 # 567 % 10 = 7 num = num // 10 # 567 // 10 = 56 # 第四步:取千位 qian = num % 10 # 56 % 10 = 6 num = num // 10 # 56 // 10 = 5 # 第五步:取万位 wan = num % 10 # 5 % 10 = 5 num = num // 10 # 5 // 10 = 0(结束) print("万位:", wan) # 5 print("千位:", qian) # 6 print("百位:", bai) # 7 print("十位:", shi) # 8 print("个位:", ge) # 9
python
def haoshu(n):
ans = 0 # 初始化好数计数器
for i in range(1, n + 1): # 遍历 1 到 n 的所有数字
digits = [] # 用于存储数字的各位数字(个位、十位、百位...)
t = i#用临时变量 t 来承接原数字 i,后续对 t 进行 "取余(%10)+ 整除(//10)" 的分解操作;保留原变量 i 的值(因为后续还需要用 i 遍历 1~n 的数字,不能破坏它)。
while t != 0: # 分解数字的各位(从右往左存)
digits.append(t % 10)
t = t // 10
# 判断是否满足好数条件,标志位
is_haoshu = True
for k in range(len(digits)):
# 奇数位(从右往左数,列表是从0开始的,k+1是实际位数):需为奇数
# 偶数位:需为偶数
if (k + 1) % 2 == 1: # 奇数位(个位、百位、万位...)
if digits[k] % 2 != 1: # 不是奇数则不满足
is_haoshu = False
break
else: # 偶数位(十位、千位、十万位...)
if digits[k] % 2 != 0: # 不是偶数则不满足
is_haoshu = False
break
if is_haoshu:
ans += 1
return ans
if __name__ == "__main__":
n = int(input()) # 输入整数 n
print(haoshu(n)) # 输出好数的个数
共性与区别分析
| 环节 | 好数统计(多数字遍历) | 幸运数字判断(单数字判断) |
|---|---|---|
| 遍历范围 | for num in 1~n(遍历所有数) |
无遍历,直接处理输入的单个数字字符串 |
| 数位分解 | 数字→分解为[个位、十位、百位...] |
字符串→直接切片前n位/后n位(更高效) |
| 核心判断 | 奇偶位对应奇偶数字 | 前后位全大 / 全小 + 前半和为偶数 |
| 结果更新 | 符合则计数器 + 1 | 符合则输出 Y,否则输出 N |
| 方式 | 适用场景 | 注意点 |
|---|---|---|
| 数字取余(%10 + //10) | 处理整数、需要逐位提取 | ① 用临时变量temp,不修改原数字;② 分解结果是 "个位在前" |
| 字符串切片 / 遍历 | 处理固定长度数字字符串 | ① 先校验长度(如幸运数字需 2n 位);② 字符直接比较(无需转数字) |
总结模板
python
def solve(n):
# 1. 初始化结果/计数器
result = 0 # 统计类题用计数器,判断类题用布尔值
# 2. 遍历目标范围(幸运数字是单个数,好数是1~n,根据题目调整)
for num in range(1, n + 1): # 幸运数字可直接处理单个num,无需遍历
# 3. 分解数位:核心步骤(保护原数字,用临时变量拆解)
digits = [] # 存储数位(默认:个位、十位、百位...从右往左)
temp = num # 临时变量,避免修改原数字
while temp != 0:
digit = temp % 10 # 取当前个位
digits.append(digit) # 存入列表
temp = temp // 10 # 去掉个位,右移一位
# 4. 核心判断:根据题目规则编写(这是唯一需要定制的部分)
is_valid = True
for idx in range(len(digits)):
# 示例:好数规则(奇数位奇、偶数位偶)
# 示例:幸运数字规则(前后半位全大/全小 + 和为偶数)
# 👇 替换成题目具体规则 👇
if 题目规则不满足:
is_valid = False
break
# 5. 结果更新
if is_valid:
result += 1 # 统计类:计数器+1;判断类:直接return True/False
# 6. 返回结果
return result
if __name__ == "__main__":
n = int(input())
print(solve(n))
最后祝各位选手取得好成绩!!!