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;

}

你可能感兴趣的:(c)