Description
给出n和m,求n!的范围中与m!互质的数的个数。答案对r取模。 n,m<=1e7,r>n>=m,且r为质数。
Solution
首先,如果gcd(a,b)=1,那么gcd(a+b,b)=1. 所以,1~km与m互质的数的个数为
k∗φ(m)
答案就是
n!m!φ(m!)
然后,
φ(m!)=m!∏p<=n且p为质数p−1p
Ans=n!∏p<=n且p为质数p−1p
O(n)线筛出范围内的所有质数和它们的逆元,顺便预处理阶乘就可以了。
Ps:逆元有线性求法。
Code
using namespace std;
typedef long long ll;
int ty,n,
m,bz[N+
5],p[N],mo,fact[N+
5],inv[N+
5],ans[N+
5];
void exgcd(
int a,
int b,
int &
x,
int &
y) {
if (!b) {
x=
1;
y=
0;
return;}
int xx,yy;exgcd(b,a
%b,xx,yy);
x=yy;
y=xx-a/b
*yy;
}
int main() {
scanf(
"%d%d",&ty,&mo);fact[
1]=ans[
1]=
1;
fo(i,
2,N) {
fact[i]=(ll)fact[i-
1]
*i%mo;
int y;
if (!bz[i]) {
p[++p[
0]]=i;exgcd(i,mo,inv[i],
y);
inv[i]=(inv[i]
%mo+mo)
%mo;
}
fo(j,
1,p[
0]) {
int k=i
*p[j];
if (k>N)
break;
bz[k]=
1;
if (!(i
%p[j]))
break;
}
}
fo(i,
2,N) {
ans[i]=ans[i-
1];
if (!bz[i]&&i!=mo) ans[i]=(ll)ans[i]
*(i-
1)
%mo*inv[i]
%mo;
}
for(;ty;ty--) scanf(
"%d%d",&n,&
m),
printf(
"%d\n",(ll)fact[n]
*ans[
m]
%mo);
}
转载请注明原文地址: https://ju.6miu.com/read-1305824.html