Description
X
A
m
o
d
P
=
B
X^A mod P = B
XAmodP=B,其中
P
P
P为质数。给出
P
P
P和
A
A
A
B
B
B,求
<
P
< P
<P的所有
X
X
X。
例如:
P
=
11
,
A
=
3
,
B
=
5
P = 11,A = 3,B = 5
P=11,A=3,B=5。
3
3
M
o
d
11
=
5
3^3 Mod 11 = 5
33Mod11=5
所有数据中,解的数量不超过
S
q
r
t
(
P
)
Sqrt(P)
Sqrt(P)。
Sample Input
3
11 3 5
13 3 1
13 2 2
Sample Output
3
1 3 9
No Solution
很久以前就做了这道题,一直没有写博客,今天写主要是怕以后忘记。
有关原根:
定义:设
g
g
g为
P
P
P的原根那么与
P
P
P互质的数,都可以由
g
g
g为底数的次幂表示出来。
一个数有原根,当且仅当这个数为:
P
=
1
,
2
,
4
,
p
a
,
2
p
a
P=1,2,4,p^a,2p^a
P=1,2,4,pa,2pa。
一个数
P
P
P,它的原根数量为
p
h
i
(
p
h
i
(
P
)
)
phi(phi(P))
phi(phi(P))。
最小的原根一般比较小,于是我们考虑暴力枚举。
判断一个数
g
g
g是否是
P
P
P的原根:
1.
1.
1.暴力枚举。
2.
2.
2.若
(
P
−
1
)
(P-1)
(P−1)的约数中有一个质数满足
g
(
P
−
1
)
/
p
i
=
=
1
(
m
o
d
P
)
g^{(P-1)/pi}==1(mod P)
g(P−1)/pi==1(modP),那么就不是原根。
说到这道题:
式子是这样的:
X
A
=
B
(
m
o
d
P
)
X^A =B(mod P)
XA=B(modP)
你设
g
t
1
=
X
(
m
o
d
P
)
g^{t1}=X(modP)
gt1=X(modP),
g
t
2
=
B
(
m
o
d
P
)
g^{t2}=B(modP)
gt2=B(modP)
那么式子就是这样的:
g
t
1
A
=
g
t
2
(
m
o
d
P
)
g^{t1A}=g^{t2}(modP)
gt1A=gt2(modP)
所以:
t
1
A
=
t
2
(
m
o
d
P
−
1
)
t1A=t2(mod P-1)
t1A=t2(modP−1)
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int mod = 1000007;
int plen, cnt;
LL o[110000];
LL head[1100000], num[110000], id[110000], next[110000];
vector<LL> a;
LL pow_mod(LL x, LL k, LL mod) {
LL ans = 1; x %= mod;
while(k) {
if(k % 2 == 1) (ans *= x) %= mod;
(x *= x) %= mod; k /= 2;
} return ans;
}
int Find(LL x) {
LL y = x - 1;
for(int i = 2; i * i <= x; i++) {
if(y % i == 0) {
a.push_back(i);
while(y % i == 0) y /= i;
}
} if(y > 1) a.push_back(y);
int o;
for(int i = 1; ;i++) {
bool bk = 1;
for(int j = 0; j < a.size(); j++) {
if(pow_mod(i, (x - 1) / a[j], x) == 1) {
bk = 0; break;
}
} if(bk) {o = i; break;}
}
return o;
}
int BSGS(int a, int b, int p) {
cnt = 0;
LL t = sqrt(p) + 1, u = 1;
for(int i = 0; i < t; i++) {
LL x = ((LL)b * u) % p;
num[++cnt] = x; id[cnt] = i;
int oo = x % mod;
if(!head[oo]) head[oo] = cnt;
else {
int y = head[oo];
while(next[y]) y = next[y];
next[y] = cnt;
}
(u *= a) %= p;
}
a = pow_mod(a, t, p);
if(a == 0) {
if(b == 0) return 1;
return -1;
} u = 1;
for(int i = 0; i <= t; i++) {
LL x = u;
int z = x % mod;
z = head[z];
while(num[z] != x && z) z = next[z];
if(num[z] == x) {
LL j = id[z];
if(i * t - j >= 0) return i * t - j;
} (u *= a) %= p;
} return -1;
}
LL exgcd(LL a, LL b, LL &x, LL &y) {
if(b == 0) {
x = 1; y = 0;
return a;
} else {
LL tx, ty;
LL d = exgcd(b, a % b, tx, ty);
x = ty; y = tx - ty * (a / b);
return d;
}
}
int main() {
int tt; scanf("%d", &tt);
while(tt--) {
LL p, a, b, x, y; scanf("%lld%lld%lld", &p, &a, &b);
LL root = Find(p);
memset(head, 0, sizeof(head));
memset(next, 0, sizeof(next));
memset(num, 0, sizeof(num));
memset(id, 0, sizeof(id));
LL c = BSGS(root, b, p);
if(c == -1) {printf("No Solution\n"); continue;}
b = p - 1;
LL d = exgcd(a, b, x, y);
if(c % d != 0) {printf("No Solution\n"); continue;}
(x *= c / d) %= b;
int len = 0;
for(int i = 1; i <= d; i++) {
(x += b / d) %= b; (x += b) %= b;
o[++len] = pow_mod(root, x, p);
} sort(o + 1, o + len + 1);
for(int i = 1; i < len; i++) printf("%d ", o[i]);
printf("%d\n", o[len]);
}
return 0;
}