BZOJ 2186: [Sdoi2008]沙拉公主的困惑

\[题意:求\frac{ n !} {m!} \cdot \varphi(m!) \]

\[如果 a与 m互质那么a + m与m互质,a+(k-1) \cdot m与m互质,那么1-k\cdot m中与m互质的个数为= k \cdot \varphi(m) \]

\[\begin{eqnarray*} \varphi (m!) & = & m! \prod \frac{p - 1} {p} (p为m的质因子) \\ ans & = & \frac{\varphi(m!) \cdot n!} {m!} \\ & = & \prod \frac{p - 1}{p} \cdot n! \\ \end{eqnarray*} \]

\[通过素数筛+线性求逆元可以预处理出\prod \frac{p-1}{p},其中p是m的质因子 \]

#include<bits/stdc++.h>
 
using namespace std;
 
typedef long long ll;
 
const int INF = 0x3f3f3f3f;
const int maxn = 1e7 + 10;
 
int t;
ll R;
ll n, m;
ll fac[maxn];
ll inv[maxn];
ll ans[maxn];
bool check[maxn];
int prime[maxn >> 1];
int tot;
 
void Init()
{
    memset(check, false, sizeof check);
    tot = 0;
    for (int i = 2; i < maxn && i < R; ++i)
    {
        if (!check[i])
        {
            prime[tot++] = i;
        }
        for (int j = 0; j < tot; ++j)
        {
            if (i * prime[j] > maxn) break;
            check[i * prime[j]] = true;
            if (i % prime[j] == 0) break;
        }
    }
    fac[1] = inv[1] = 1;
    for (int i = 2; i < maxn && i < R; ++i)
    {
        fac[i] = fac[i - 1] * i % R;
        inv[i] = inv[R % i] * (R - R / i) % R;
    }
    ans[1] = 1;
    for (int i = 2; i < maxn && i < R; ++i)
    {
        ans[i] = ans[i - 1];
        if (!check[i]) ans[i] = ans[i] * (i - 1) % R * inv[i] % R;
    }
}
 
 
void RUN()
{
    while (~scanf("%d %lld", &t, &R))
    {
        Init();
        for (int cas = 1; cas <= t; ++cas)
        {
            scanf("%lld %lld", &n, &m);
            printf("%lld\n", fac[n] * ans[m] % R);
        }
    }
}
 
int main()
{
#ifdef LOCAL_JUDGE
    freopen("Text.txt", "r", stdin);
#endif // LOCAL_JUDGE
 
    RUN();
 
    return 0;
}
posted @ 2019-04-13 10:46  薛37  阅读(70)  评论(0编辑  收藏  举报