题目描述

给定数列 an{a_n}:a0=1a_0=1,ai+1=(A×ai+ai mod B) mod Ca_{i+1}=(A\times a_i + a_i\bmod B)\bmod C,其中 0≤A,B,C≤1090\le A,B,C\le 10^9。输入一行三个整数 A,B,CA,B,C,输出该数列第一次出现重复项的标号,若该标号超过 2×1062\times10^6 则输出 −1-1。样例输入 2 2 9,样例输出 4。

思路

递推式是一个函数迭代,每项只由前一项决定,所以重复必然出现。从 a0=1a_0=1 起逐项模拟,用哈希集合记录已经出现过的值,第一次撞上旧值的下标就是答案。值域 CC 可达 10910^9 开不下标记数组,但模拟步数不超过 2×1062\times10^6,集合大小只与出现过的项数有关;注意 a0=1a_0=1 也要先放进集合,且“超过 2×1062\times10^6”不含恰好等于。

参考代码

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-09-30 12:24
# update_at: 2026-09-30 12:24

import sys

LIMIT = 2 * 10**6  # 题面规定:答案超过 2×10^6 输出 -1,所以最多往后模拟这么多项


def first_repeat(a: int, b: int, c: int) -> int:
    """返回数列第一次出现重复项的下标;若首次重复发生在 LIMIT 之后则返回 -1。"""
    value, seen = 1, {1}  # a_0 = 1;seen 是已经出现过的项的集合
    for i in range(1, LIMIT + 1):
        value = (a * value + value % b) % c
        if value in seen:
            return i  # value 之前出现过,i 就是第一次出现重复的标号
        seen.add(value)
    return -1


def solve() -> None:
    a, b, c = map(int, sys.stdin.buffer.read().split())
    print(first_repeat(a, b, c))


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 00:12
 * update_at: 2026-10-06 00:12
 */

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const ll LIMIT = 2000000; // 题目规定:答案超过 2×10^6 就输出 -1,所以最多模拟这么多项

ll A, B, C;

void solve() {
    // 数列是函数迭代,重复一定会出现;逐项模拟,第一次撞上旧值即答案。
    // 每项都在 [0, C) 内,但 C 可达 10^9 开不下标记数组;而模拟步数不超过 2×10^6,
    // 所以用哈希集合只登记真正出现过的值,集合大小与值域无关。
    unordered_set<ll> seen; // seen 记录已经出现过的项
    seen.reserve(LIMIT + 1);

    ll value = 1; // a_0 = 1,它也可能再次出现,必须先放进集合
    seen.insert(value);

    for (ll i = 1; i <= LIMIT; i++) {
        value = (A * value + value % B) % C;
        if (seen.count(value) != 0) {
            cout << i << '\n'; // value 之前出现过,标号 i 就是第一次出现重复的位置
            return;
        }
        seen.insert(value);
    }

    cout << -1 << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> A >> B >> C;
    solve();

    return 0;
}