答案为n!m!∗m!∗(primei−1primei)(mod p)n!m!∗m!∗(primei−1primei)(mod p)
那么预处理即可,然后用快速幂算逆元
c++代码如下:
#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i = x;i <= y; ++ i)
#define repd(i,x,y) for(register int i = x; i >= y; -- i)
using namespace std;
typedef long long ll;
template<typename T>inline void read(T&x)
{
char c;int sign = 1;x = 0;
do { c = getchar(); if(c == '-') sign = -1; }while(!isdigit(c));
do { x = x * 10 + c - '0'; c = getchar(); }while(isdigit(c));
x *= sign;
}
const int N = 1e7+50;
int t,p,n,m,prime[N],cnt,fac[N],a[N],b[N];
bool vis[N];
inline void pre()
{
a[1] = b[1] = 1;
rep(i,2,10000000)
{
if(!vis[i]) prime[++cnt] = i,a[i] = 1ll * a[i - 1] * (i - 1) % p,b[i] = 1ll * b[i - 1] * i % p;
else a[i] = a[i - 1] , b[i] = b[i - 1];
for(register int j = 1; j <= cnt && 1ll*prime[j] * i <= 10000000; ++ j)
{
vis[i*prime[j]] = 1;
if(i % prime[j] == 0 )
break;
}
}
fac[0] = 1;rep(i,1,10000000) fac[i] = 1ll * fac[i - 1] * i % p;
}
inline int quick_pow(int x,int y)
{
int ans = 1;
while(y)
{
if(y&1) ans = 1ll * ans * x % p;
x = 1ll * x * x % p;
y >>= 1;
}
return ans;
}
inline void solve()
{
read(n); read(m);
printf("%lld\n",1ll * fac[n] * a[m] % p * quick_pow(b[m],p - 2)% p );
}
int main()
{
read(t); read(p);
pre();
while(t -- )
solve();
return 0;
}
本文介绍了一种基于组合数学的算法实现,并结合快速幂计算逆元的方法来解决特定问题。通过预处理阶乘和利用快速幂计算逆元,提高了算法效率。
910

被折叠的 条评论
为什么被折叠?



