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;
}