从 M+1 起线性搜索,用位运算 O(L) 判定循环数:各位非零互异,且按下标跳格恰好走遍所有位回到起点。
OJ: roj
题目 ID: 2028
难度:普及-
标签:模拟枚举
创建: 2026-10-01 04:05
更新: 2026-10-06 09:51
题目描述
求严格大于
思路
从
参考代码
Python 版:
python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-10-01 04:20
# update_at: 2026-10-01 04:20
import sys
MAX_RUNAROUND = 9682415 # 位数递增时循环数总数为 9+20+12+48+160+96+112,7 位以上为空
def is_runaround(n: int) -> bool:
"""n 的十进制各位非零且互不相同,且从第 0 位起按"当前位数字"跳格恰好走遍所有位并回到 0。"""
s = str(n)
if '0' in s or len(set(s)) != len(s): # 含 0 或数字重复,直接排除
return False
length = len(s)
pos, visited = 0, 0
for _ in range(length):
if visited >> pos & 1: # 同一位置踩两次:说明跳格没覆盖全部位,绕不到起点
return False
visited |= 1 << pos
pos = (pos + int(s[pos])) % length # 向右数 s[pos] 格,越界则回卷
return pos == 0 # 恰好走完 length 步后回到起点
def solve() -> None:
m = int(sys.stdin.buffer.read())
n = m + 1
while n <= MAX_RUNAROUND and not is_runaround(n): # 超过上界就不存在更大的循环数
n += 1
print(n)
if __name__ == "__main__":
solve()C++ 版(同一算法):
cpp
/**
* Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
* rbook: -> https://rbook.roj.ac.cn https://rbook2.roj.ac.cn
* rainboy的学习导航网站: https://idx.roj.ac.cn
* create_at: 2026-10-06 09:51
* update_at: 2026-10-06 09:51
*/
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const ll MAX_RUNAROUND = 9682415; // 循环数最大为 9682415,7 位以上不存在
// 判断 n 是否为循环数:各位非零互异,且从第 0 位起按当前位数字跳格走遍所有位并回到 0
bool is_runaround(ll n) {
char s[32];
snprintf(s, sizeof(s), "%lld", n);
int len = strlen(s);
bool seen[10] = {false};
for (int i = 0; i < len; i++) {
int d = s[i] - '0';
if (d == 0) return false; // 含 0 直接排除
if (seen[d]) return false; // 数字重复直接排除
seen[d] = true;
}
int pos = 0;
int visited = 0; // 用 bitmask 记录已访问的下标
for (int i = 0; i < len; i++) {
if (visited >> pos & 1) return false; // 重复踩点,未走遍全部位
visited |= 1 << pos;
pos = (pos + (s[pos] - '0')) % len;
}
return pos == 0;
}
int main() {
ll m;
scanf("%lld", &m);
ll n = m + 1;
// 线性搜索第一个大于 m 的循环数,超过上界则停止
while (n <= MAX_RUNAROUND && !is_runaround(n)) n++;
printf("%lld\n", n);
return 0;
}