zoukankan      html  css  js  c++  java
  • 关于 BSGS 以及 ExBSGS 算法的理解

    BSGS

    引入

    求解关于(X)的方程,

    [A^Xequiv B pmod P ]

    其中(Gcd(A,P)=1)

    求解

    我们令(X=i*sqrt{P}-j),其中(0<=i,j<=sqrt{P})
    则原式可以变为:

    [A^Xequiv B pmod P ]

    [A^{i*sqrt{P}-j}equiv B pmod P ]

    由于(Gcd(A,P)=1),则可以恒等变化为:

    [A^{i*sqrt{P}}equiv B*A^j pmod P ]

    则我们可以先预处理出所有的(A^{i*sqrt{P}}),存入哈希表。
    再枚举(B*A^j),在哈希表里查找即可得解。

    代码

    int quick_Pow(int x,int y,int p){
    	if(y==0)return 1;
    	if(y==1)return x;
    	if(y%2)return 1ll*x*quick_Pow(1ll*x*x%p,y/2,p)%p;
    	return quick_Pow(1ll*x*x%p,y/2,p);
    }
    void BSGS(int x,int y,int p){
    	x%=p;y%=p;
    	if(x==0&&y!=0){puts("-1");return ;}
    	if(x==0&&y==0){puts("1");return ;}
    	if(y==1){puts("0");return ;}
    	int st=int(sqrt(p))+1;Mp.clear();
    	for(int i=1,rt=1;i<=st;i++,rt=(1ll*rt*x)%p)Mp[rt]=i;
    	int sum=quick_Pow(x,st,p);
    	for(int i=1,rt=1;i<=st;i++){
    		rt=(1ll*rt*sum)%p;
    		if(Mp[rt]){
    			printf("%d
    ",i*st-Mp[rt]);
    			return ;
    		}
    	}
    	puts("-1");
    }
    

    ExBSGS

    引入

    求解关于(X)的方程,

    [A^Xequiv B pmod P ]

    其中(Gcd(A,P))无特殊条件。

    由于(Gcd(A,P))可能不为(1),所以(A)关于(P)可能没有逆元。
    故不能用一般的 BSGS 求解。

    求解

    我们设(D=Gcd(A,P))
    则显然有 (frac{A}{D}equiv 1pmod P)
    则原式$$A^Xequiv B pmod P$$
    可恒等变形为$$A^{X-1}cdotfrac{A}{D}equiv frac{B}{D} pmod {frac{P}{D}}$$
    而由于(Gcd(frac{A}{D},frac{P}{D})=1),则有

    [A^{X-1}equiv frac{B}{D}cdot({frac{A}{D}})^{-1} pmod {frac{P}{D}} ]

    则此时(frac{P}{D})就相当于新的(P)值,(frac{B}{D}cdot({frac{A}{D}})^{-1})就相当于新的(B)值,
    就可以这样递推下去了。(注:下一次的(D)是新的(P)值与(A)(Gcd)

    考虑边界状态:
    ①:若当前的(D=1),则问题转化为普通的 BSGS。
    ②:若(B)值等于(1)了,则迭代到的(Ans)值为(1)
    ③:若(D mid B),即(D)不是(B)的因数,则(frac{B}{D})没有意义,则无解。

    综上,出解。

    例题及代码

    板题
    题意:求满足(A^Xequiv B pmod{P})的最小整数(X)

    #include<map>
    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    #include<tr1/unordered_map>
    using namespace std;
    #define LL long long
    tr1::unordered_map<LL,int>Mp;
    LL Gcd(LL x,LL y){
    	if(x==0)return y;
    	return Gcd(y%x,x);
    }
    LL quick_Pow(LL x,LL y,LL p){
    	if(y==0)return 1;
    	if(y==1)return x;
    	if(y%2)return x*quick_Pow(x*x%p,y/2,p)%p;
    	return quick_Pow(x*x%p,y/2,p);
    }
    int ExBSGS(int x,int y,int p){
    	if(y==1)return 0;//特判解为0的情况.
    	LL k=0,a=1;
    	while(1){
    		int d=Gcd(x,p);if(d==1)break;
    		if(y%d)return -1;
    		y/=d;p/=d;k++;a=(1ll*a*x/d)%p;
    		if(a==y)return k;//同特判.
    	}Mp.clear();
    	LL st=int(sqrt(p))+1,sum=quick_Pow(x,st,p);
    	for(LL i=0,rt=y;i<=st;i++,rt=(1ll*rt*x)%p)Mp[rt]=i+1;
    	for(LL i=1,rt=(a*sum)%p;i<=st;i++,rt=(1ll*rt*sum)%p){//不将求解中的A/D移项.
    		if(!Mp[rt])continue;
    		return 1ll*i*st-(Mp[rt]-1)+k;
    	}
    	return -1;
    }
    int A,B,C;
    int main(){
    	while(~scanf("%d%d%d",&A,&B,&C)&&A){
    		int Ans=ExBSGS(A,C,B);
    		if(Ans!=-1)printf("%d
    ",Ans);
    		else puts("Orz,I can’t find D!");
    	}
    }
    

    注:一般的,题目所给的A,B,C都是正整数。

  • 相关阅读:
    HDU 1025 Constructing Roads In JGShining's Kingdom (DP+二分)
    HDU 1158 Employment Planning
    HDU 2059 龟兔赛跑
    Csharp 简单操作Word模板文件
    Csharp windowform datagridview Clipboard TO EXCEL OR FROM EXCEL DATA 保存datagridview所有數據
    Csharp 讀寫文件內容搜索自動彈出 AutoCompleteMode
    Csharp windowform controls clear
    CSS DIV大图片右上角叠加小图片
    Csharp DataGridView自定义添加DateTimePicker控件日期列
    Csharp 打印Word文件默認打印機或選擇打印機設置代碼
  • 原文地址:https://www.cnblogs.com/ftotl/p/11621342.html
Copyright © 2011-2022 走看看