P2155 [SDOI2008]沙拉公主的困惑

P2155 SDOI2008沙拉公主的困惑
我们显然可以知道,本题是求 \(\displaystyle \sum_{i=1}^{N!}[\gcd(i, M!) =1]\)
那么我们 莫比乌斯反演 可以分块求一下。

\[\frac{N!}{M!} \cdot M! \prod_{\tiny \begin{matrix}p\in prime\\p \mid M!\end{matrix}} \frac{p-1}{p} = N! \prod_{\tiny \begin{matrix}p\in prime\\p \mid M!\end{matrix}} \frac{p-1}{p} \]

看出这是个欧拉函数,然而多组询问,那么我们预处理一下。

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

typedef long long ll;
const ll MAXN = 1e7+10;

ll T, R, N, M, cnt, ans[MAXN], prime[MAXN], inv[MAXN], fac[MAXN];
bool vis[MAXN];

void ini();

int main() {
    ios::sync_with_stdio(false);
    cin >> T >> R;
    ini();
    while (T--) {
        cin >> N >> M;
        printf("%lld\n", fac[N] * ans[M] % R);
    }
    return 0;
}

void ini() {
    fac[1] = 1, fac[0] = 1, inv[1] = 1, inv[0] = 1, ans[0] = 1, ans[1] = 1;
    for (ll i = 2; i <= MAXN - 10; i++) {
        if (!vis[i]) prime[++cnt] = i;
        for (ll j = 1; j <= cnt && prime[j] * i <= MAXN - 10; j++) {
            vis[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
        }
    }
    for (ll i = 2; i <= MAXN - 10; i++) inv[i] = inv[R % i] * (R - R / i) % R, fac[i] = fac[i-1] * i % R;
    for (ll i = 2; i <= MAXN - 10; i++) {
        ans[i] = ans[i-1];
        if (!vis[i]) ans[i] = ans[i] * (i-1) % R * inv[i] % R;
    }
}
posted @ 2020-09-23 16:49  Gensokyo_Alice  阅读(87)  评论(0编辑  收藏  举报