题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2186
本题参考了:http://blog.csdn.net/acdreamers/article/details/19068791
学到了一种新的求乘法逆元的方法,博文推导中不明白的地方也在评论中得到了解答~
#include <cstdio>
#include <bitset>
using namespace std;
#define i64 long long
const int N = 10000005;
bitset<N> prime;
int mod;
i64 fac[N],ans[N];
i64 inv[N];
void Init ()
{
int i,j;
prime.set();
for (i=2; i<N; i++) if (prime[i])
for (j=i+i;j<N;j+=i)
prime[j] = false;
fac[0]=1; //阶乘
for (i=1;i<N;i++)
fac[i]=fac[i-1]*i %mod;
inv[1]=1; //逆元
for (i=2;i<N;i++)
{
if(i >= mod) break;
inv[i] = (mod - mod / i) * inv[mod % i] % mod;
}
ans[1]=1;
for (i=2; i<N; i++)
if (prime[i])
{
ans[i] = ans[i-1] * (i - 1) % mod;
ans[i] = ans[i] * inv[i % mod] % mod;
}
else
ans[i] = ans[i-1];
}
int main ()
{
int T;
scanf("%d%d",&T,&mod);
Init ();
while(T--)
{
int m,n;
scanf("%d%d",&n,&m);
i64 res=fac[n]*ans[m]%mod;
printf("%lld\n",res);
}
return 0;
}