多次剩余:
求 x a = b ( m o d p ) x^{a}=b(mod~p) xa=b(mod p),p是质数的所有解。
找到p的原根g,设 g B = b g^{B}=b gB=b,这个用bsgs求。
x a = b ( m o d p ) x^a=b(mod~p) xa=b(mod p)
等价于 g a ∗ x = g B ( m o d p ) g^{a*x}=g^{B}(mod~p) ga∗x=gB(mod p)
a ∗ x = B ( m o d ( p − 1 ) ) a*x=B(mod~(p-1)) a∗x=B(mod (p−1))
那么用exgcd解即可。
例题:
http://www.51nod.com/Challenge/AcceptedRank.html#!#problemId=1038
卡常:写bsgs时可以利用边集数组,会比哈希表快一些。
#include
#include
#include
#include
#define ll long long
#define pp printf
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;
int T;
ll a, b, mo, g;
ll u[20], v[20], u0;
ll ksm(ll x, ll y) {
ll s = 1;
for(; y; y /= 2, x = x * x % mo)
if(y & 1) s = s * x % mo;
return s;
}
void fen(ll x) {
u0 = 0;
for(int i = 2; i * i <= x; i ++) if(x % i == 0) {
u[++ u0] = i; v[u0] = 0;
while(x % i == 0) x /= i, v[u0] ++;
}
if(x > 1) u[++ u0] = x, v[u0] = 1;
}
int pdg(int x) {
fo(i, 1, u0) if(ksm(x, (mo - 1) / u[i]) == 1) return 0;
return 1;
}
void fg() {
fo(i, 2, mo) if(pdg(i))
{ g = i; return;}
}
const int M = 1e5 + 7;
int fi[M], to[M], nt[M], V[M], tot;
void link(int x, int y, int z) {
nt[++ tot] = fi[x], to[tot] = y, V[tot] = z, fi[x] = tot;
}
int bsgs(int a, int b) {
tot = 0; memset(fi, 0, sizeof fi);
int m = ceil(sqrt(mo));
ll x = b;
fo(i, 1, m) {
x = x * a % mo;
link(x % M, x, i);
}
x = 1; ll am = ksm(a, m);
fo(i, 1, m) {
x = x * am % mo;
for(int j = fi[x % M]; j; j = nt[j])
if(to[j] == x) return i * m - V[j];
}
return -1;
}
int gcd(int x, int y) {
return !y ? x : gcd(y, x % y);
}
void exgcd(int a, int b, int &x, int &y) {
if(!b) {x = a; y = 0; return;}
exgcd(b, a % b, y, x); y -= (a / b) * x;
}
int ans[100000];
void gg(int a, int b, int c) {
int d = gcd(a, b);
if(c % d) return;
a /= d; b /= d; c /= d;
int x, y; exgcd(a, b, x, y);
x = (ll) (x % b + b) * c % b;
fo(i, 1, d) ans[++ ans[0]] = (i - 1) * b + x;
}
int main() {
for(scanf("%d", &T); T; T --) {
scanf("%lld %lld %lld", &mo, &a, &b);
if(mo == 2) {
if(b == 0) pp("1\n0\n"); else
pp("1\n1\n");
continue;
}
fen(mo - 1); fg();
int B = bsgs(g, b);
ans[0] = 0;
gg(a, mo - 1, B);
fo(i, 1, ans[0]) ans[i] = ksm(g, ans[i]);
sort(ans + 1, ans + ans[0] + 1);
ans[0] = unique(ans + 1, ans + ans[0] + 1) - (ans + 1);
if(ans[0] == 0) {
pp("No Solution\n");
} else {
fo(i, 1, ans[0]) pp("%d ", ans[i]);
pp("\n");
}
}
}