zoukankan      html  css  js  c++  java
  • BSGS算法

    BSGS算法

    求关于x的方程a^x = b(mod p),gcd(a,p) = 0下的x;

    算法流程:

    令x = am -b
    y^(am-b) = z(mod p)
    y^am = zy^b (mod p)
    枚举b = [0,m-1],map记录右边的值,枚举左边的a= [1,m+1]
    每次查询右边map中是否有左边的值。O(sqrt(p))

    模板:https://www.luogu.com.cn/problem/P3846

    ll a,b,p;
    ll qpw(ll a,ll b,ll p) {
    	a%=p;
    	ll ans = 1;
    	while(b) {
    		if(b & 1)ans = ans*a%p;
    		a = a*a%p;
    		b>>=1;
    	}
    	return ans%p;
    }
    
    map<ll,ll>mp;
    
    ll BSGS(ll a,ll b,ll p) {  //返回-1表示没找到
    	mp.clear();
    	if(b == 1) {
    		return 0;
    	}
    	ll ans=-1,m=sqrt(p)+1,xx,s=b;
    	for(int i=0; i<m; i++) {
    		mp[s] = i;  //右边对应的b
    		s = 1ll*s*a%p;
    	}
    	xx = qpw(a,m,p),s=1;  //左边
    	for(int i=1; i<=m+1; i++) {
    		s=1ll*s*xx%p;
    		if(mp.count(s)) {
    			ans = i*m-mp[s];
    			break;
    		}
    	}
    	if(ans < 0)return -1;
    	else return ans;
    }
    

    ex_BSGS : 若gcd(a,b) != 0

    算法流程挺烦的,不管了 https://www.luogu.com.cn/problem/P4195

    ll ex_BSGS(ll a,ll b,ll p) {
    	mp.clear();
    	if(b == 1)return 0;
    	ll cnt = 0,t=1,s,xx,m;
    	for(int d=gcd(a,p); d!=1; d=gcd(a,p)) {
    		if(b % d)return -1;
    		++cnt,b/=d,p/=d,t=1ll*t*a/d%p;
    		if(b == t)return cnt;
    	}
    	s=b,m=sqrt(p)+1;
    	for(int i=0; i<m; i++) {
    		mp[s] = i;
    		s=1ll*s*a%p;
    	}
    	xx = qpw(a,m,p),s=t;
    	for(int i=1; i<=m; i++) {
    		s=1ll*s*xx%p;
    		if(mp.count(s))return i*m-mp[s]+cnt;
    	}
    	return -1;
    }
    
  • 相关阅读:
    C++中类模板的概念和意义
    欢迎访问新博客aiyoupass.com
    P2327
    P2885
    P1968
    Link-Cut-Tree
    树的重心
    点分治笔记
    SPOJ 375
    树链剖分
  • 原文地址:https://www.cnblogs.com/LaiYiC/p/14729228.html
Copyright © 2011-2022 走看看