首先這個 \(C(i, j)\bmod j\) 的形式就非常怪,於是首先肯定要先研究一下這個值。
先考慮如何求 \(C(i, j)\)。
可以考慮先選出要用的 \(j\) 個數,再乘上其排列成環的方案數,那麼有 \(C(i, j) = \binom{i}{j}\times (j - 1)!\)。
那麼就是來考慮 \(\binom{i}{j}\times (j - 1) ! \bmod j\) 的值了。
注意到後面的這個 \((j - 1)! \bmod j\) 是個定值,於是考慮分析這個值。
首先若 \(j\in \mathbb{P}\),根據威爾遜定理那麼有 \((j - 1)!\bmod j = j - 1\)。
否則若 \(j = 1\),顯然為 \(0\)。
接下來就考慮 \(j\) 為合數的情況了,感受一下會覺得其實這些值大部分都為 \(0\)。
考慮令 \(j = x\times p^k\),那麼 \((j - 1)!\bmod j \not = 0\) 就肯定要使得 \(k\ge x\times p^{k - 1}\not = 1\)(\(= 1\) 就為質數了)。
那麼就能發現只可能在取 \(x = 1, p = 2, k = 2\) 時有解,即 \(j = 4\) 時。
那麼對於 \(j = 4\),顯然是最特殊的,但是考慮到也只有這一種 \(j\),所以直接考慮直接預處理 \(\binom{i}{4}\times 6 \bmod 4\) 然後字首和。
那麼就只需要考慮 \(j\in \mathbb{P}\) 的情況了。
那麼此時化簡一下就有 \(\binom{i}{j}\times (j - 1)! \bmod j = \binom{i}{j}\times (j - 1)\bmod j = (j\binom{i}{j} - \binom{i}{j})\bmod j = (j - \binom{i}{j}\mod j)\mod j\)。
於是問題來到如何求 \(\binom{i}{j}\bmod j\)。
注意到此時 \(j\in \mathbb{P}\),那麼就可以用 Lucas 定理了。
此時 \(\binom{i}{j}\bmod j = \binom{\lfloor\frac{i}{j}\rfloor}{\lfloor\frac{j}{j}\rfloor}\binom{i\bmod j}{j\bmod j} = \binom{\lfloor\frac{i}{j}\rfloor}{1}\binom{i\bmod j}{0} = \lfloor\frac{i}{j}\rfloor\times 1 = \lfloor\frac{i}{j}\rfloor\)。
於是 \(C(i, j) = (j - \lfloor\frac{i}{j}\rfloor)\bmod j\)。
注意到 \(x\in [kj, (k + 1)j)\) 都有 \(C(x, j) = (j - k\bmod j)\bmod j\),這說明實際上可以把這些 \(k\) 相同的 \(x\) 用差分來處理,就只需要對於每個 \(k\) 處理一次了。
那麼這個 \(k\) 的上限就是 \(\lceil\frac{n}{j}\rceil\)。
那麼複雜度就是與埃氏篩相同的 \(\mathcal{O}(n\log \log n)\)。
最後總時間複雜度 \(\mathcal{O}(n\log \log n + t)\)。
#include<bits/stdc++.h>
constexpr int mod = 1e9 + 7;
constexpr int maxn = 1e6 + 10, N = 1e6;
int a[maxn], vis[maxn];
inline void init() {
for (int i = 2; i <= N; i++) {
if (vis[i]) continue;
for (int j = 0, k = 0; j <= N; j += i, k = (i + k - 1) % i) {
vis[j] = 1;
(a[j] += k) %= mod, (a[std::min(N + 1, j + i)] += mod - k) %= mod;
}
}
for (int i = 1; i <= N; i++) {
(a[i] += a[i - 1]) %= mod;
}
for (int i = 1; i <= N; i++) {
(a[i] += ((__int128_t)i * (i - 1) * (i - 2) * (i - 3) / 4) % 4) %= mod;
}
for (int i = 1; i <= N; i++) {
(a[i] += a[i - 1]) %= mod;
}
}
inline void solve() {
int n;
scanf("%d", &n);
printf("%d\n", a[n]);
}
int main() {
init();
for (int T, _ = scanf("%d", &T); T--; ) {
solve();
}
return 0;
}