zoukankan      html  css  js  c++  java
  • hdu 3930 Broot 二次剩余

    模素数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)

    /*
     * hdu3930.c
     *
     *  Created on: 2011-10-12
     *      Author: bjfuwangzhu
     */
    
    #include<math.h>
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #define LL long long
    #define nmax 1000010
    typedef struct num {
    	int ii;
    	LL value;
    } num;
    num Num[nmax];
    int flag[nmax], prime[nmax], cpfactor[100];
    LL pfactor[100];
    int plen, len_pfactor;
    LL k, n, p, proot, x, y;
    void mkprime() {
    	int i, j;
    	memset(flag, -1, sizeof(flag));
    	for (i = 2, plen = 0; i < nmax; i++) {
    		if (flag[i]) {
    			prime[plen++] = i;
    		}
    		for (j = 0; (j < plen) && (i * prime[j] < nmax); j++) {
    			flag[i * prime[j]] = 0;
    			if (i % prime[j] == 0) {
    				break;
    			}
    		}
    	}
    }
    void findpFactor(LL n) {
    	int i, te, cnt;
    	te = (int) sqrt(n * 1.0);
    	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] = (LL) prime[i];
    			cpfactor[len_pfactor++] = cnt;
    		}
    	}
    	if (n > 1) {
    		pfactor[len_pfactor] = n;
    		cpfactor[len_pfactor++] = 1;
    	}
    }
    
    LL modular_multi(LL a, LL b, LL c) {
    	LL res, temp;
    	res = 0, temp = a % c;
    	while (b) {
    		if (b & 1) {
    			res += temp;
    			if (res >= c) {
    				res -= c;
    			}
    		}
    		temp <<= 1;
    		if (temp >= c) {
    			temp -= c;
    		}
    		b >>= 1;
    	}
    	return res;
    }
    /*快速幂取余a^b%c*/LL modular_exp(LL a, LL b, LL c) {
    	LL res, temp;
    	res = 1 % c, temp = a % c;
    	while (b) {
    		if (b & 1) {
    			res = modular_multi(res, temp, c);
    		}
    		temp = modular_multi(temp, temp, c);
    		b >>= 1;
    	}
    	return 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;
    		}
    	}
    }
    LL extend_gcd(LL a, LL b) {
    	LL 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(LL 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;
    	LL temp = n.value - m.value;
    	if (temp > 0) {
    		return 1;
    	} else if (temp < 0) {
    		return -1;
    	}
    	return 0;
    }
    /* a^x = b (mod c)*/LL baby_step_giant_step(LL a, LL b, LL c) {
    	int i, j, te;
    	LL temp, xx, aa;
    	te = (int) (sqrt(c * 1.0) + 0.5);
    	for (i = 0, temp = 1 % c; i <= te; i++) {
    		Num[i].ii = i;
    		Num[i].value = 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 = x;
    		xx = xx * b;
    		xx = xx % c + c;
    		x = xx % c;
    		j = bfindNum(x, te + 1);
    		if (j != -1) {
    			return (LL) (i) * te + j;
    		}
    		temp = temp * aa % c;
    	}
    	return -1;
    }
    int rcmp(const void *a, const void *b) {
    	LL temp = *(LL *) a - *(LL *) b;
    	if (temp > 0) {
    		return 1;
    	} else if (temp < 0) {
    		return -1;
    	}
    	return 0;
    
    }
    /* ax = b (mod c)*/LL result[1001];
    void solve(LL a, LL b, LL c) {
    	int i;
    	LL d;
    	d = extend_gcd(a, c);
    	if (b % d) {
    		puts("-1");
    		return;
    	}
    	b /= d, c /= d;
    	result[0] = ((LL) x * b % c + c) % c;
    	for (i = 1; i < d; i++) {
    		result[i] = result[i - 1] + c;
    	}
    	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("%I64d\n", result[i]);
    	}
    }
    int main() {
    #ifndef ONLINE_JUDGE
    	freopen("data.in", "r", stdin);
    #endif
    	int cas;
    	LL a, b, c;
    	mkprime();
    	cas = 0;
    	/*x^k = n (mod p) */
    	while (~scanf("%I64d %I64d %I64d", &k, &p, &n)) {
    		primitive();
    		b = baby_step_giant_step(proot, n, p);
    		a = k, c = p - 1;
    		printf("case%d:\n", ++cas);
    		solve(a, b, c);
    	}
    	return 0;
    }
    
  • 相关阅读:
    深析Tomcat容器工作流程
    GC基础
    oracle sql总结
    mybatis返回值类型总结
    eclipse启动javaweb项目后,如何让局域网内的其他人访问
    oracle sql 逗号 分割 REGEXP_SUBSTR 函数
    Oracle12c安装时报"指定的oracle主目录用户已存在"错误
    spring
    Oracle sql where后面的多条件case when判断执行
    Oracle12c安装时报ins-30131
  • 原文地址:https://www.cnblogs.com/xiaoxian1369/p/2210216.html
Copyright © 2011-2022 走看看