zoukankan      html  css  js  c++  java
  • BSGS exBGS

    BSGS

    求离散对数,即给出(a,b,p),求最小非负整数(x)满足:

    [a^x equiv b (mod p) ]

    其中(gcd(a,p)=1)

    (y=sqrt{p})

    1.把(a)(0...y-1)次幂(*b)塞到哈希表里。

    2.枚举(i),看下是否存在(a^{iy-j}equiv b (mod p))

    ​ 即(a^{iy}equiv a^jb (mod p))

    (jin [0,y-1]),所以在哈希表里查一下就行了。

    exBSGS

    不保证(gcd(a,p)=1)

    如果(gcd(a,p) mid b)则无解(写成方程就知道了)。

    否则

    [a^{x-1}frac{a}{d} equiv frac{b}{d} (mod frac{p}{d}) ]

    如果变成(a^x=0)就返回除的次数;如果(gcd(a,p)=1)就变成前面带个系数的(BSGS),也就(a^iy)变成(Aa^iy)而已。

    洛谷模板题

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    namespace Hash_Table{
    	const int md=19260817;
    	int T,tot,hd[md],nxt[100010],num[100010],val[100010],tim[100010];
    	void add(int x,int y){
    		int i=x%md;
    		if (tim[hd[i]]<T) hd[i]=0;
    		nxt[++tot]=hd[i],hd[i]=tot;
    		num[tot]=x,val[tot]=y;
    		tim[tot]=T;
    	}
    	int qry(int x){
    		int i=x%md;
    		if (tim[hd[i]]<T) return -1;
    		for (int j=hd[i];j;j=nxt[j])
    			if (num[j]==x) return val[j];
    		return -1;
    	}
    }
    int power(int x,int p,int md){
    	int ret=1;
    	for (;p;p>>=1,x=1ll*x*x%md)
    		if (p&1) ret=1ll*ret*x%md;
    	return ret;
    }
    int phi(int n){
    	int ret=n;
    	for (int i=2;i*i<=n;++i)
    		if (n%i==0){
    			ret=ret/i*(i-1);
    			for (;n%i==0;n/=i);
    		}
    	if (n>1) ret=ret/n*(n-1);
    	return ret;
    }
    int gcd(int x,int y){
    	if (!y) return x;
    	else return gcd(y,x%y);
    }
    int bsgs(int a,int b,int p,int A){
    	++Hash_Table::T,Hash_Table::tot=0;
    	int y=sqrt(p)+1,num=b,sum;
    	for (int i=0;i<y;++i,num=1ll*num*a%p) Hash_Table::add(num,i);
    	num=power(a,y,p),sum=1ll*A*num%p;
    	for (int i=1,x;i<=y+1;++i,sum=1ll*sum*num%p){
    		x=Hash_Table::qry(sum);
    		if (x!=-1) return i*y-x;
    	}
    	return -1;
    }
    int exbsgs(int a,int b,int p){
    	int ret=0,num=1;
    	for (int d;;){
    		d=gcd(a,p);
    		if (d==1) break;
    		if (b%d) return -1;
    		p/=d,b/=d,++ret,num=1ll*num*a/d%p;
    		if (num==b) return ret;
    	}
    	return ret+bsgs(a,b,p,num);
    }
    int a,b,p;
    int main()
    {
    	for (scanf("%d%d%d",&a,&p,&b);a||b||p;){
    		a%=p,b%=p;
    		int x=exbsgs(a,b,p);
    		if (x>=0) printf("%d
    ",x);
    		else puts("No Solution");
    		scanf("%d%d%d",&a,&p,&b);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Android内存优化5 了解java GC 垃圾回收机制3
    一起刑事案件法庭辩护 z
    辩护技巧总结——律师在刑事辩护中应注意的几个问题 z
    证据对抗、证据链标准 z
    里德九步审讯法 z
    WCF服务在高并发情况下报目标积极拒绝的异常处理 z
    C#EasyHook例子C# Hook 指定进程C#注入指定进程 z
    玄机论坛Socket类库源码 当前版本 2.6.3 更新日期:10-09/2015 z
    庭审全程文字实录 z
    庭审精彩语录整理 z
  • 原文地址:https://www.cnblogs.com/zzqtxdy/p/12874298.html
Copyright © 2011-2022 走看看