1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| #include <bits/stdc++.h> using namespace std; typedef long long LL; const LL MAX_LEN = 1000000 + 5; const LL P = LL(1E9) + 7; const LL PHI_P = LL(1E9) + 6; const LL INV_6 = 166666668; inline LL getPow(LL u, LL v) { LL ret = 1; while (v) { if (v & 1) ret = ret * u % P; u = u * u % P; v >>= 1; } return ret; } inline LL add(LL u, LL v, LL x = 0, LL y = 0) { return (((u + v) % P) + ((x + y) % P) % P); } inline LL sub(LL u, LL v) { return (((u - v) % P) + P) % P; } inline LL mul(LL u, LL v, LL x = 1, LL y = 1) { return (((u * v) % P) * ((x * y) % P) % P); } bool vis[MAX_LEN]; LL p[MAX_LEN], low[MAX_LEN], tot; LL f[MAX_LEN]; void linearSieve() { vis[0] = vis[1] = 1; low[1] = f[1] = 1; for (LL i = 2; i < MAX_LEN; ++i) { if (!vis[i]) { p[++tot] = i; f[i] = sub(i * i % P, 1); low[i] = i; } for (LL j = 1; j <= tot && i * p[j] < MAX_LEN; ++j) { vis[i * p[j]] = 1; if (i % p[j] == 0) { low[i * p[j]] = low[i] * p[j]; if (low[i] == i) f[i * p[j]] = mul(p[j], p[j]) * f[i] % P; else f[i * p[j]] = f[i / low[i]] * f[p[j] * low[i]] % P; break; } else { f[i * p[j]] = f[i] * f[p[j]] % P; low[i * p[j]] = p[j]; } } } for (LL i = 1; i < MAX_LEN; ++i) f[i] = (f[i] + f[i - 1]) % P; } unordered_map <LL, LL> hashS; LL F(LL x) { if (x < MAX_LEN) return f[x]; if (hashS.find(x) != hashS.end()) return hashS[x]; LL ret = mul(x, x + 1, x * 2 + 1, INV_6); LL l, r; for (l = 2; l <= x; l = r + 1) { r = x / (x / l); ret = sub(ret, F(x / l) * (r - l + 1) % P); ret = ((ret % P) + P) % P; } return hashS[x] = ret; } const LL MAX_N = 100000 + 5; LL T, N, K, SP; char str[MAX_N]; int main() { linearSieve(); scanf("%lld", &T); for (LL cs = 1; cs <= T; ++cs) { hashS.clear(); scanf("%lld", &N); scanf("%s", str); LL len = strlen(str); K = 0; SP = 0; for (LL i = 0; i < len; ++i) { K = (K * 10 + (str[i] - '0')) % PHI_P; SP = (SP * 10 + (str[i] - '0')) % P; } K = ((K - 1) % PHI_P + PHI_P) % PHI_P; SP = ((SP - 1) % P + P) % P; LL l, r, ans = 0; for (l = 1; l <= N; l = r + 1) { r = N / (N / l); LL b = N / l; LL invDown = getPow(sub(1, b), P - 2); LL right = sub(1, getPow(b, K)); LL con = mul(b, b, invDown, right); if (b == 1) con = SP; ans = add(ans, mul(con, sub(F(r), F(l - 1)))); } printf("%lld\n", ans); } return 0; }
|