题目大意:
T组数据,
T
<
=
10000
T<=10000
T<=10000
每组给出
m
,
n
,
m
<
=
n
m,n,m<=n
m,n,m<=n
求
[
1
,
n
!
]
[1,n!]
[1,n!]中与
m
!
m!
m!互质的数,结果对p取模
p
<
=
1
0
9
+
10
p<=10^9+10
p<=109+10
1
<
=
n
,
m
<
=
10000000
1 < = n , m < = 10000000
1<=n,m<=10000000
分析:
g
c
d
(
a
,
b
)
=
1
(
a
x
1
+
b
y
1
=
1
)
gcd(a,b)=1(ax1+by1=1)
gcd(a,b)=1(ax1+by1=1)
则有
g
c
d
(
a
+
b
,
b
)
=
1
[
a
x
2
+
b
(
x
2
+
y
2
)
=
1
]
gcd(a+b,b)=1[ax2+b(x2+y2)=1]
gcd(a+b,b)=1[ax2+b(x2+y2)=1]
那么对于b而言,显然每b个数里面与b互质的数的数量相同
题目要求的是
g
c
d
(
a
,
m
!
)
=
1
(
a
∈
[
1
,
n
!
]
)
gcd(a,m!)=1(a∈[1,n!])
gcd(a,m!)=1(a∈[1,n!])
那么因为
m
!
∣
n
!
m!|n!
m!∣n!
g
c
d
(
a
,
m
!
)
=
1
gcd(a,m!)=1
gcd(a,m!)=1则有
g
c
d
(
a
+
m
!
,
m
!
)
=
1
gcd(a+m!,m!)=1
gcd(a+m!,m!)=1
所以答案可以写成
φ
(
m
!
)
∗
(
n
!
/
m
!
)
φ(m!)*(n!/m!)
φ(m!)∗(n!/m!)
也就是
(
m
!
∗
π
i
=
1
k
(
p
i
−
1
)
/
p
i
)
∗
(
n
!
/
m
!
)
(m!*π_{i=1}^{k}(p_i-1)/p_i)*(n!/m!)
(m!∗πi=1k(pi−1)/pi)∗(n!/m!)
约一下就是
π
i
=
1
k
(
p
i
−
1
)
/
p
i
∗
n
!
π_{i=1}^{k}(p_i-1)/p_i*n!
πi=1k(pi−1)/pi∗n!
预处理一下然后O(1)回答即可
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <cstring>
#include <algorithm>
#define rep(i, st, ed) for (int i = st; i <= ed; i++)
#define rwp(i, ed, st) for (int i = ed; i >= st; i--)
#define N 10000005
using namespace std;
typedef long long ll;
int pri[N], mul[N], inv[N], num[N], T, mulsum, mo, cnt;
bool vis[N];
void Pre_Work() {
num[1] = 1;
inv[1] = 1; rep(i, 2, N - 5) inv[i] = (ll)(mo - mo / i) * inv[mo % i] % mo;
mul[0] = 1; rep(i, 1, N - 5) mul[i] = (ll)mul[i - 1] * i % mo;
mulsum = 1;
rep(i, 2, N - 5) {
if (!vis[i]) { pri[++cnt] = i; mulsum = (ll)mulsum * (i - 1) % mo * inv[i] % mo; }
num[i] = mulsum;
rep(j, 1, cnt) {
if ((ll)i * pri[j] > N - 5) break;
vis[i * pri[j]] = 1;
if (i % pri[j] == 0) break;
}
}
}
int main() {
scanf("%d %d", &T, &mo);
Pre_Work();
int L, R;
rep(i, 1, T) {
scanf("%d %d", &R, &L);
int ans = (ll)mul[R] * num[L] % mo;
ans = (ans % mo + mo) % mo;
printf("%d\n", ans);
}
return 0;
}