// 不要为了省什么内存把数组开小,会卡80#include <cmath>#include <iostream>#include <map>using namespace std;constexpr int N = 5e6, NP = 5e6, SZ = N;long long n, P, inv2, inv6, s[N];int phi[N], p[NP], cnt, pn;bool bp[N];map<long long, long long> s_map;long long ksm(long long a, long long m) { // 求逆元用 long long res = 1; while (m) { if (m & 1) res = res * a % P; a = a * a % P, m >>= 1; } return res;}void prime_work(int k) { // 线性筛phi,s bp[0] = bp[1] = true, phi[1] = 1; for (int i = 2; i <= k; i++) { if (!bp[i]) p[++cnt] = i, phi[i] = i - 1; for (int j = 1; j <= cnt && i * p[j] <= k; j++) { bp[i * p[j]] = true; if (i % p[j] == 0) { phi[i * p[j]] = phi[i] * p[j]; break; } else phi[i * p[j]] = phi[i] * phi[p[j]]; } } for (int i = 1; i <= k; i++) s[i] = (1ll * i * i % P * phi[i] % P + s[i - 1]) % P;}long long s3(long long k) { // 立方和 return k %= P, (k * (k + 1) / 2) % P * ((k * (k + 1) / 2) % P) % P;}long long s2(long long k) { // 平方和 return k %= P, k * (k + 1) % P * (k * 2 + 1) % P * inv6 % P;}long long calc(long long k) { // 计算S(k) if (k <= pn) return s[k]; if (s_map[k]) return s_map[k]; // 对于超过pn的用map离散存储 long long res = s3(k), pre = 1, cur; for (long long i = 2, j; i <= k; i = j + 1) j = k / (k / i), cur = s2(j), res = (res - calc(k / i) * (cur - pre) % P) % P, pre = cur; return s_map[k] = (res + P) % P;}long long solve() { long long res = 0, pre = 0, cur; for (long long i = 1, j; i <= n; i = j + 1) { j = n / (n / i); cur = calc(j); res = (res + (s3(n / i) * (cur - pre)) % P) % P; pre = cur; } return (res + P) % P;}int main() { cin.tie(nullptr)->sync_with_stdio(false); cin >> P >> n; inv2 = ksm(2, P - 2), inv6 = ksm(6, P - 2); pn = (long long)pow(n, 0.666667); // n^(2/3) prime_work(pn); cout << solve(); return 0;}