• POJ2417 Baby-Step-Gaint-Step 算法


    考虑一个问题:A^x%p=B,给定A,B,p,求x的最小非负整数解。

    在p是质数的情况下,这个问题比較简单。

    A^x=B(mod P) (P is a Prime, A,B<P)
    Let m = floor(sqrt(P))
    Put A^0,A^1,...A^(m-1) into HashSet(You Can Also Use Map in STL),for Example M[A^i]=i.
    if A^i=A^j(i<j), M[A^i=A^j]=i.
    Enumerate i, Let x=i*m+j, A^(i*m)*A^j=B(mod C)
    Let E=A^(i*m),F=A^j,E*F=B(mod P) because (E,C)=1,(E,C)|B,we can use EXTgcd to get F.
    If F is in the HashSet,then the minimum answer x=i*m+M[F].
    Because P is a Prime, and A,B<P, then A^(P-1)=1(mod P). 
    Then if a answer exists, the minimum answer must less then P.
    So the range of i is [0,P/m].
    If for all i we cannot find a answer, then no solution.
    
    
    我亲手胡乱写的东西,能看懂才怪!


    再附上代码吧:(我的小数据范围是暴力的)

    #include <cmath>
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    typedef long long LL;
    inline void Exgcd(LL a, LL b, LL &d, LL &x, LL &y) {
    	if (!b) { d = a, x = 1, y = 0; }
    	else { Exgcd(b, a % b, d, y, x), y -= x * (a / b); }
    }
    inline LL gcd(LL a, LL b) {
    	return (!b) ? a : gcd(b, a % b);
    }
    inline LL Solve(LL a, LL b, LL c) { // ax=b(mod c)
    	LL d, x, y;
    	Exgcd(a, c, d, x, y);
    	return (x + c) % c * b % c;
    }
    LL ksm(LL x, LL y, LL p) {
    	LL res = 1, t = x;
    	for(; y; y >>= 1) {
    		if (y & 1) res = res * t % p;
    		t = t * t % p;
    	}
    	return res;
    }
    
    const int mod = 13131;
    struct Hashset {
    	int head[mod], next[40010], f[40010], v[40010], ind;
    	void reset() {
    		ind = 0;
    		memset(head, -1, sizeof head);
    	}
    	void insert(int x, int _v) {
    		int ins = x % mod;
    		for(int j = head[ins]; j != -1; j = next[j])
    			if (f[j] == x) {
    				v[j] = min(v[j], _v);
    				return;
    			}
    		f[ind] = x, v[ind] = _v;
    		next[ind] = head[ins], head[ins] = ind++;
    	}
    	int operator [] (const int &x) const {
    		int ins = x % mod;
    		for(int j = head[ins]; j != -1; j = next[j])
    			if (f[j] == x)
    				return v[j];
    		return -1;
    	}
    }S;
    
    int main() {
    	LL A, B, C;
    	LL i;
    	while(scanf("%I64d%I64d%I64d", &C, &A, &B) == 3) {
    		if (C <= 100) {
    			LL d = 1;
    			bool find = 0;
    			for(i = 0; i < C; ++i) {
    				if (d == B) {
    					find = 1;
    					printf("%I64d
    ", i);
    					break;
    				}
    				d = d * A % C;
    			}
    			if (!find)
    				puts("no solution");
    		}
    		else {
    			int m = (int)sqrt(C);
    			S.reset();
    			LL d = 1;
    			for(i = 0; i < m; ++i) {
    				S.insert(d, i);
    				d = d * A % C;
    			}
    			bool find = 0;
    			int ins;
    			for(i = 0; i * m < C; ++i) {
    				LL t = Solve(ksm(A, i * m, C), B, C);
    				if ((ins = S[t]) != -1) {
    					printf("%I64d
    ", i * m + ins);
    					find = 1;
    					break;
    				}
    			}
    			if (!find)
    				puts("no solution");
    		}
    	}
    	
    	return 0;
    }


  • 相关阅读:
    欧拉定理 (证明+在求逆元上的应用)
    【转】弱校的ACM奋斗史
    SDUT 2412 (单调队列 + dp)
    做SRM感想。。。
    平面图中最小割向最短路的转化
    HDU 4533
    黑书上的DP 30题
    POJ【数论/组合/博弈论】题目列表
    HDU 4534 郑厂长系列故事——新闻净化
    SRM 571
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/6873159.html
Copyright © 2020-2023  润新知