洛谷P1662题:环形报数游戏与方向反转策略详解

一、问题分析
题目要求模拟1337人围成一圈的报数游戏,规则如下:
从1号开始正向报数(1,2,3...)
当报的数字包含7或是7的倍数时,报数方向立即反转
报数到第X个数字时,输出当前报数人的编号
二、完整代码
#include <iostream>
using namespace std;
// 检查数字是否包含7或者是7的倍数
bool containsSeven(int num) {
// 检查是否是7的倍数
if (num % 7 == 0)
return true;
// 逐位检查数字是否包含7
while (num > 0) {
if (num % 10 == 7) // 检查当前位是否为7
return true;
num /= 10; // 移除已检查的最低位
}
return false;
}
int main() {
int X; // 要报数的总次数
cin >> X; // 输入X
const int N = 1337; // 总人数
int current = 1; // 当前报数人的编号(初始为1号)
int direction = 1; // 报数方向:1表示正向,-1表示反向
// 模拟报数过程,从1报到X
for (int num = 1; num <= X; ++num) {
// 如果当前数字包含7或是7的倍数,反转方向
if (containsSeven(num)) {
direction *= -1; // 反转方向(1变-1,-1变1)
}
// 移动到下一个人(最后一个数字不需要移动)
if (num < X) {
current += direction; // 根据方向移动到相邻位置
// 处理环形边界(超过最大值时回到1)
if (current > N)
current = 1;
// 处理环形边界(小于最小值时回到1337)
if (current < 1)
current = N;
}
}
// 输出最终报数人的编号
cout << current << endl;
return 0;
}三、算法解析
1. 数字特性检查函数
bool containsSeven(int num) {
if (num % 7 == 0) return true; // 7的倍数检查
while (num > 0) {
if (num % 10 == 7) return true; // 逐位检查数字7
num /= 10; // 数字右移
}
return false;
}数学特性利用:
num % 7 == 0判断7的倍数逐位分解:通过循环
num % 10和num /= 10检查每一位数字复杂度:O(log n),与数字位数成正比
2. 环形报数模拟
current += direction; // 方向控制移动 // 环形边界处理 if (current > 1337) current = 1; if (current < 1) current = 1337;
方向变量:
direction=1正向,direction=-1反向环形处理技巧:
超过1337时回到1(
current = 1)小于1时回到1337(
current = N)边界判断:最后一个数字报完不移动
3. 反转触发机制
if (containsSeven(num)) {
direction *= -1; // 简洁的方向反转}即时反转:满足条件时立即改变方向
累积效应:多次触发会导致方向连续反转
四、常见错误
边界处理错误:未考虑环形边界导致的越界
反转时机错误:在移动后检查数字特性
包含7判断错误:漏掉数字中间或结尾的7
最后一个数字处理:报完最后一个数字后不应移动
方向变量初始化:初始方向应为正方向(1)
原创内容 转载请注明出处
