hrbeu 1318 X^a mod b=c 二次剩余
模素数p的原根g的优美体现在每个模p的非零数以g的幂次出现。所以,对任何数1 <= a < p,我们可选择幂
g,g^2,g^2,```````,g^(p-2),g^(p-1)
中恰好一个与a模p同余。相应的指数被称为以g为底的a模p的指标。假设p与g已给定,则记指标为I(a)。
以下以2模13的所有幂的形式:
I 1 2 3 4 5 6 7 8 9 10 11 12
2^I(mod 13) 2 4 8 3 6 12 11 9 5 10 7 1
例如,为求I(11),我们搜寻表的第二行直到找到数11,则指标I(11)=7可从第一行得到。
指标法则
a). I(ab)=I(a)+I(b) (mod p-1)
b). I(a^k)=kI(a) (mod p-1)
g^I(ab)=ab=g^I(a)g^I(b)=g^(I(a)+I(b)) (mod p)
故有g^I(x) = x (mod p-1)
也可以这么理解:g^I(value) = id (mod p-1)
例题:3*x^30=4(mod 37)
I(3*x^30)=I(4)
I(3)+30*I(x)=I(4) (mod 36)
26+30*I(x)=2 (mod 36)
30*I(x)=-24=12 (mod 36)
对于这里I(4)=2解释一下:
其实就是g^2 = 4 (mod 36)
其实这个可以根据g^x =b (mod p)来求
对于本题,g就是37的原根2,b=I(x) p =36
也就是求满足2^x = I(x) (mod 36)的x。用Baby Step Giant Step算法即可哦
提醒:两边不要除以6以得到5*I(x)+2 (mod 36),否则会丢失一些解。
ax = c (mod m)
由扩展欧几里德,知:
I(x)=4,10,16,22,28,34
最后,有指标表(书论书上有哦,自己不放写程序看看),得到x的对应值
I(16)=4,I(25)=10,I(9)=16
I(21)=22,I(12)=28,I(28)=34
其实这里,也可以根据指标的原式公式g^I(x) = x (mod p-1)
故,同余式3*x^30=4 (mod 37)有6个解,即
x=16,25,9,21,12,28 (mod 37)
/*
* hrbeu1318.c
*
* Created on: 2011-10-13
* Author: bjfuwangzhu
*/
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#define LL long long
#define nmax 4001
typedef struct num {
int ii, value;
} num;
num Num[nmax];
int flag[nmax], prime[nmax], pfactor[nmax], cpfactor[nmax];
int plen, len_pfactor, k, n, p, proot, x, y;
void mkprime() {
int i, j;
memset(prime, -1, sizeof(prime));
for (i = 2; i < nmax; i++) {
if (prime[i]) {
for (j = i + i; j < nmax; j += i) {
prime[j] = 0;
}
}
}
for (i = 2, plen = 0; i < nmax; i++) {
if (prime[i]) {
prime[plen++] = i;
}
}
}
void findpFactor(int n) {
int i, te, cnt;
te = (int) sqrt(1.0 * n);
for (i = 0, len_pfactor = 0; (i < plen) && (prime[i] <= te); i++) {
if (n % prime[i] == 0) {
cnt = 0;
while (n % prime[i] == 0) {
cnt++;
n /= prime[i];
}
pfactor[len_pfactor] = prime[i];
cpfactor[len_pfactor++] = cnt;
}
}
if (n > 1) {
pfactor[len_pfactor] = n;
cpfactor[len_pfactor++] = 1;
}
}
/*快速幂取余a^b%c*/
int modular_exp(int a, int b, int c) {
LL res, temp;
res = 1 % c, temp = a % c;
while (b) {
if (b & 1) {
res = res * temp % c;
}
temp = temp * temp % c;
b >>= 1;
}
return (int) res;
}
int dfs(int depth, LL now) {
int i;
LL res, temp;
if (depth == len_pfactor) {
res = modular_exp(proot, now, p);
if ((res == 1) && (now != (p - 1))) {
return 0;
}
return 1;
}
for (i = 0, temp = 1; i <= cpfactor[depth]; i++) {
if (!dfs(depth + 1, now * temp)) {
return 0;
}
temp = temp * pfactor[depth];
}
return 1;
}
void primitive() {
findpFactor(p - 1);
for (proot = 2;; proot++) {
if (dfs(0, 1)) {
return;
}
}
}
int extend_gcd(int a, int b) {
int d, xx;
if (b == 0) {
x = 1, y = 0;
return a;
}
d = extend_gcd(b, a % b);
xx = x;
x = y, y = xx - a / b * y;
return d;
}
int bfindNum(int key, int n) {
int left, right, mid;
left = 0, right = n;
while (left <= right) {
mid = (left + right) >> 1;
if (Num[mid].value == key) {
return Num[mid].ii;
} else if (Num[mid].value > key) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return -1;
}
int cmp(const void *a, const void *b) {
num n = *(num *) a;
num m = *(num *) b;
return n.value - m.value;
}
/* a^x = b (mod c)*/
int baby_step_giant_step(int a, int b, int c) {
int i, j, te, aa;
LL temp, xx;
te = (int) (sqrt(1.0 * c) + 0.5);
for (i = 0, temp = 1 % c; i <= te; i++) {
Num[i].ii = i;
Num[i].value = (int) (temp);
temp = temp * a % c;
}
aa = Num[te].value;
qsort(Num, te + 1, sizeof(Num[0]), cmp);
for (i = 0, temp = 1; i <= te; i++) {
extend_gcd((int) (temp), c);
xx = (LL) x;
xx = xx * b;
xx = xx % c + c;
x = (int) (xx % c);
j = bfindNum(x, te + 1);
if (j != -1) {
return i * te + j;
}
temp = temp * aa % c;
}
return -1;
}
int rcmp(const void *a, const void *b) {
return *(int *) a - *(int *) b;
}
/* ax = b (mod c)*/
int result[nmax];
void solve(int a, int b, int c) {
int i, d, cc;
d = extend_gcd(a, c);
if (b % d) {
puts("No Solution!");
return;
}
cc = c;
b /= d, c /= d;
result[0] = ((LL) x * b % c + c) % c;
for (i = 1; i < d; i++) {
result[i] = (result[i - 1] + c) % cc;
}
for (i = 0; i < d; i++) {
result[i] = modular_exp(proot, result[i], p);
}
qsort(result, d, sizeof(result[0]), rcmp);
for (i = 0; i < d; i++) {
printf("%d\n", result[i]);
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif
int a, b, c;
mkprime();
/*x^k = n (mod p) */
while (~scanf("%d %d %d", &k, &p, &n)) {
primitive();
b = baby_step_giant_step(proot, n, p);
a = k, c = p - 1;
solve(a, b, c);
printf("\n");
}
return 0;
}

浙公网安备 33010602011771号