题意
[题目描述]
整除符号为
∣
|
∣,
d
∣
n
d|n
d∣n在计算机语言中可被描述为
n
%
d
=
=
0
n\% d == 0
n%d==0。
现有一算式
n
∣
x
m
−
x
n|x^m -x
n∣xm−x,给定
n
n
n,
m
m
m,求
[
1
,
n
]
[1,n]
[1,n]以内
x
x
x解的个数。
解可能很大,输出取模
998244353
998244353
998244353。
[输入格式]
从文件 d i v i s i o n . i n division.in division.in中读入数据。
其中
n
n
n的给定方式是由
c
c
c个不超过
t
t
t的质数的乘积给出的,
c
c
c和
t
t
t的范围会在数据范围中给出。
第一行一个
i
d
id
id表示这个数据点的标号。
多组数据,其中第二行一个整数
T
T
T表示数据组数。
对于每一组数据:
第一行两个整数
c
c
c和
m
m
m。
第二行
c
c
c个整数,这些整数都是质数,且两两不同,他们的乘积即为
n
n
n。
由于你可以通过输入求出
t
t
t,输入不再给出。
[输出格式]
输出到文件 d i v i s i o n . o u t division.out division.out中。
对于每组数据输出一行,表示解的个数。
[样例1输入]
0
1
2 3
2 3
[样例1输出]
6
[数据范围与提示]
测试点编号 | c ≤ c≤ c≤ | t ≤ t≤ t≤ | m ≤ m≤ m≤ | T ≤ T≤ T≤ |
---|---|---|---|---|
1 | 2 | 1 0 3 10^3 103 | 2 2 2 | 50 |
2 | 2 | 1 0 3 10^3 103 | 1 0 9 10^9 109 | 50 |
3 | 2 | 1 0 2 10^2 102 | 2 2 2 | 10000 |
4 | 1 | 1 0 4 10^4 104 | 2 2 2 | 50 |
5 | 2 | 1 0 4 10^4 104 | 2 2 2 | 50 |
6-8 | 10 | 1 0 4 10^4 104 | 1 0 9 10^9 109 | 50 |
9-10 | 50 | 1 0 4 10^4 104 | 1 0 9 10^9 109 | 50 |
题解
x
m
−
1
≡
0
(
m
o
d
n
)
x^{m-1}≡0(\bmod n)
xm−1≡0(modn)的解的个数,在[1,n-1]范围内就是
g
c
d
(
m
−
1
,
n
−
1
)
gcd(m-1,n-1)
gcd(m−1,n−1)。
原问题求
x
m
≡
x
(
m
o
d
p
1
p
2
.
.
.
p
c
)
x^m≡x(\bmod p_1p_2...p_c)
xm≡x(modp1p2...pc)
可以将其化为
{
x
m
−
1
≡
1
(
m
o
d
p
1
)
x
m
−
1
≡
1
(
m
o
d
p
2
)
.
.
.
x
m
−
1
≡
1
(
m
o
d
p
c
)
\begin{cases} x^{m-1}≡1(\bmod p_1) \\ x^{m-1}≡1(\bmod p_2) \\ ...\\ x^{m-1}≡1(\bmod p_c) \\ \end{cases}
⎩⎪⎪⎪⎨⎪⎪⎪⎧xm−1≡1(modp1)xm−1≡1(modp2)...xm−1≡1(modpc)
注意到从每个方程的一个合法解中任取一个乘起来,就能够组成一个原方程合法的解
因此我们就只用算每个方程的解就好了…
而单个方程的解的个数就为 gcd ( m − 1 , p − 1 ) + 1 \gcd(m-1,p-1)+1 gcd(m−1,p−1)+1。
乘起来即可。
证明:
我们要求满足 x ∈ [ 1 , p ] x∈[1,p] x∈[1,p]时 x m ≡ x ( m o d p ) x^m≡x (\bmod p) xm≡x(modp) 的 x x x 的个数。
首先 x = p x=p x=p 一定满足,故不特殊考虑,最后答案 + 1 +1 +1 即可。接下来只考虑 x ∈ [ 1 , p − 1 ] x∈[1,p−1] x∈[1,p−1] 的情况。由于 p p p 为质数,因此 p p p存在一个原根 g g g, [ 1 , p − 1 ] [1,p−1] [1,p−1]内的任意数在 m o d p \bmod p modp 意义下都可以表示为 g y g^y gy 的形式。这样,原方程就转化为:
g m y ≡ g y ( m o d p ) g^{my}≡g^y (\bmod p) gmy≡gy(modp)
根据费马小定理:
m y ≡ y ( m o d p − 1 ) ⇒ ( m − 1 ) y ≡ 0 ( m o d p − 1 ) my≡y (\bmod p−1)⇒(m−1)y≡0 (\bmod p−1) my≡y(modp−1)⇒(m−1)y≡0(modp−1)
令 k = gcd ( m − 1 , p − 1 ) k=\gcd(m−1,p−1) k=gcd(m−1,p−1),两边同时除以 kk,得:
m − 1 k y ≡ 0 ( m o d p − 1 k ) \frac{m−1}{k}y≡0 (mod \frac{p−1}{k}) km−1y≡0(modkp−1)
由于此时 g c d ( m − 1 k , p − 1 k ) = 1 gcd(\frac{m−1}{k},\frac{p−1}{k})=1 gcd(km−1,kp−1)=1,因此 y y y 一定有 p − 1 k ∣ y \frac{p−1}{k}|y kp−1∣y。由于 y ∈ [ 0 , p − 2 ] y∈[0,p−2] y∈[0,p−2],显然, p − 1 k \frac{p−1}{k} kp−1 的任意小于 k k k 的非负整数倍( 0 ∼ k − 1 0∼k−1 0∼k−1 倍)均满足条件,因此 y y y 共有 k k k 种合法取值。
因此满足 ∑ x = 1 p [ x m ≡ x m o d p ] ∑^p_{x=1}[x^m≡x \bmod p] ∑x=1p[xm≡xmodp] 的 i i i 共有 k + 1 k+1 k+1个。
[来自ImagineC大佬]
实现
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define MAXN 10000000
#define LL long long
#define MOD 998244353
int T,n,m;
int gcd(int a,int b){
return (!b)?a:gcd(b,a%b);
}
int main()
{
freopen("division.in","r",stdin);
freopen("division.out","w",stdout);
scanf("%*d%d",&T);
while(T--){
scanf("%d%d",&n,&m);
LL ans=1;
for(int i=1;i<=n;i++){
int x;scanf("%d",&x);
ans=ans*(gcd(x-1,m-1)+1)%MOD;
}printf("%lld\n",ans);
}
}