#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<algorithm>
#include<map>
#define LL long long
using namespace std;
const int N = 1000000;
int T;
LL n, mod;
int cnt;
LL primes[N], phi[N], mu[N], sum[N], sum1[N];
bool st[N];
map<LL, LL>w;
map<int, int>mp;
void init()
{
mu[1] = 1;
phi[1] = 1;
for(int i = 2;i < N;i ++)
{
if(!st[i]) primes[++ cnt] = i, mu[i] = -1, phi[i] = i - 1;
for(int j = 1;j <= cnt && primes[j] * i < N;j ++)
{
st[primes[j] * i] = 1;
phi[i * primes[j]] = phi[i] * primes[j] % mod;
if(i % primes[j] == 0) break;
mu[i * primes[j]] = -mu[i];
phi[i * primes[j]] = phi[i] * phi[primes[j]] % mod;
}
}
for(int i = 1;i < N;i ++) sum1[i] = (sum1[i - 1] + phi[i] * i % mod * i % mod) % mod;
}
LL inv2, inv6;
LL Sum(LL x){x %= mod;return x * (x + 1) % mod * inv2 % mod;}
LL Sum2(LL x){x %= mod;return x * (x + 1) % mod * (x + x + 1) % mod * inv6 % mod;}
LL qpow(LL x, LL k)
{
LL res = 1;
while(k)
{
if(k & 1) res = (res * x) % mod;
x = (x * x) % mod;
k >>= 1;
}
return res;
}
LL ph(LL x)
{
if(x < N) return sum1[x];
if(w.find(x) != w.end()) return w[x];
LL ans = Sum(x);
ans = (ans * ans) % mod;
for(LL l = 2, r;l <= x;l = r + 1)
{
r = x / (x / l);
LL s = (Sum2(r) - Sum2(l - 1)) % mod;
ans -= s * ph(x / l) % mod;
ans %= mod;
}
return w[x] = (ans + mod) % mod;
}
int main()
{
scanf("%lld%lld", &mod, &n);
init();
inv2 = qpow(2, mod - 2);
inv6 = qpow(6, mod - 2);
LL ans = 0;
for(int l = 1, r;l <= n;l = r + 1)
{
r = n / (n / l);
LL s = (ph(r) - ph(l - 1)) % mod;
LL t = Sum(n / l);
t = (t * t) % mod;
ans += s * t % mod;
ans %= mod;
}
printf("%lld", (ans + mod) % mod);
return 0;
}
为什么线性筛1e6就TLE,筛1e7就RE啊