版权声明:本文是蒟蒻写的,转载。。。随便吧 https://blog.csdn.net/xgc_woker/article/details/85638510
Description
,其中
为质数。给出
和
,求
的所有
。
例如:
。
所有数据中,解的数量不超过
。
Sample Input
3
11 3 5
13 3 1
13 2 2
Sample Output
3
1 3 9
No Solution
很久以前就做了这道题,一直没有写博客,今天写主要是怕以后忘记。
有关原根:
定义:设
为
的原根那么与
互质的数,都可以由
为底数的次幂表示出来。
一个数有原根,当且仅当这个数为:
。
一个数
,它的原根数量为
。
最小的原根一般比较小,于是我们考虑暴力枚举。
判断一个数
是否是
的原根:
暴力枚举。
若
的约数中有一个质数满足
放个结论,逃~
说到这道题:
式子是这样的:
你设
,
那么式子就是这样的:
所以:
#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;
}