Problem:
Score : 500 points

Problem Statement

Let us denote by f(x, m) the remainder of the Euclidean division of x by m.

Let A be the sequence that is defined by the initial value A_1=X and the recurrence relation A_{n+1} = f(A_n^2, M).
Find \displaystyle{\sum_{i=1}^N A_i}.

Constraints

1 \leq N \leq 10^{10}

0 \leq X < M \leq 10^5

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N X M

Output

Print \displaystyle{\sum_{i=1}^N A_i}.

Sample Input 1

6 2 1001

Sample Output 1

1369

The sequence A begins 2,4,16,256,471,620,\ldots Therefore, the answer is 2+4+16+256+471+620=1369.

Sample Input 2

1000 2 16

Sample Output 2

6

The sequence A begins 2,4,0,0,\ldots Therefore, the answer is 6.

Sample Input 3

10000000000 10 99959

Sample Output 3

492443256176507

Solution in C++ (GCC 9.2.1) (judge verdict: Runtime Error)


#include <bits/stdc++.h>
using namespace std;
#define rep(i,n) for (int i=(0);(i)<(int)(n);++(i))
using ll = long long;
using P = pair<int, int>;
using namespace std;

#define INF ((1<<30)-1)
#define LLINF (1LL<<60)
#define EPS (1e-10)

ll f(ll x, ll m) {
    return x % m;
}

ll sums[201010];

int main() {
    ll N, X, M;
    cin >> N >> X >> M;

    if (N <= 1000000) {
        ll sum = X;
        ll A = f(X * X, M);
        rep(i, N-1) {
            sum += A;
            A = f(A * A, M);
        }
        cout << sum << endl;
    }
    else {
        ll sum = X, cnt = 1;
        ll A = X;
        map<ll, ll> nxt;
        rep(i, N-1) {
            if (nxt.find(A) == nxt.end()) {
                // ない場合
                ll nxtA = f(A * A, M);

                if (nxtA == 0) {
                    cout << sum << endl;
                    return 0;
                }
                
                cnt++;
                sum += nxtA;
                nxt[A] = nxtA;
                A = nxtA;
            }
            else {
                break;
            }
        }

        ll tmpA = A, cur2 = 0;
        while (true) {
            A = f(A * A, M);
            sums[cur2] = A;
            if (cur2 > 0) sums[cur2] += sums[cur2-1];
            cur2++;
            if (A == tmpA) {
                break;
            }
        }

        //cout << cur2 << ", " << sums[cur2-1] << endl;

        // 残り個数
        ll let = N - cnt;

        // ループ分足し合わせる
        sum += (let / cur2) * sums[cur2-1];
        // 使った分引く
        let %= cur2;
        if (let > 0) sum += sums[let-1];

        cout << sum << endl;
    }
}