码迷,mamicode.com
首页 > 其他好文 > 详细

BSGS&EXBSGS 大手拉小手,大步小步走

时间:2018-07-04 01:03:53      阅读:294      评论:0      收藏:0      [点我收藏+]

标签:sed   str   oid   i++   class   ace   ase   find   splay   

BSGS代码:

技术分享图片
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<map>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=46349;
const int mod=100003;
ll p,A,B;
ll ni[N];
struct node{
    int nxt[mod],val[mod],id[mod],cnt;
    int hd[mod];
    void init(){
        memset(nxt,0,sizeof nxt),memset(val,0,sizeof val);cnt=0;
        memset(hd,0,sizeof hd);memset(id,0,sizeof id);
    }
    void insert(ll x,int d){
        int st=x%mod;
        for(int i=hd[st];i;i=nxt[i]){
            if(val[i]==x) return;
        }
        val[++cnt]=x;nxt[cnt]=hd[st];id[cnt]=d;hd[st]=cnt;
    }
    int find(ll x){
        int st=x%mod;
        for(int i=hd[st];i;i=nxt[i]){
            if(val[i]==x) return id[i];
        }
        return -233;
    }
}ha;
map<ll,int>mp;
ll qm(ll a,ll b){
    ll ret=1,base=a;
    while(b){
        if(b&1) ret=(ret*base)%p;
        base=(base*base)%p;
        b>>=1;
    }
    return ret;
}
ll BSGS(){
    ll up=(ll)floor(sqrt(1.0*p-1))+1;
    cout<<up<<endl;
    ni[0]=1;
    for(int i=1;i<=up;i++){
        ni[i]=qm(qm(A,i*up),p-2);
    }
    for(int i=0;i<up;i++){
        ll t=qm(A,i);
        ha.insert(t,i);
    }
    for(int i=0;i<=up;i++){
        if(i*up>p-1) break;
        ll ri=B*ni[i]%p;
        ll ret=ha.find(ri);
        if(ret>=0) return i*up+ret;
    }
    return -233;
}
int main()
{
    while(scanf("%lld",&p)!=EOF){
        scanf("%lld%lld",&A,&B);
        ha.init();
        ll ret=BSGS();
        if(ret==-233){
            puts("no solution");
        }
        else{
            printf("%lld\n",ret);
        }
    }
    return 0;
}
BSGS

EXBSGS代码:poj3243

技术分享图片
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=31630;//sqrt fai()
const int mod=100003;
ll C,A,B;
ll ni[N];
struct node{
    int nxt[mod],val[mod],id[mod],cnt;
    int hd[mod];
    void init(){
        memset(nxt,0,sizeof nxt),memset(val,0,sizeof val),memset(id,0,sizeof id);
        memset(hd,0,sizeof hd),cnt=0;
    }
    void insert(ll x,int d){
        int st=x%mod;
        for(int i=hd[st];i;i=nxt[i]){
            if(val[i]==x) return;
        }
        val[++cnt]=x,nxt[cnt]=hd[st],id[cnt]=d,hd[st]=cnt;
    }
    int find(ll x){
        int st=x%mod;
        for(int i=hd[st];i;i=nxt[i]){
            if(val[i]==x) return id[i];
        }    
        return -233;
    }
}ha;
int pr[N],ci[N];
int tot;
ll kuai(ll a,ll b){
    ll ret=1,base=a;
    while(b){
        if(b&1) ret=(base*ret);
        base=base*base;
        b>>=1;
    }
    return ret;
}
ll fai(ll x){
    memset(ci,0,sizeof ci);tot=0;
    for(int i=2;i*i<=x;i++){
        if(x%i==0){
            pr[++tot]=i;
            while(x%i==0){
                ci[tot]++;
                x/=i;
            }
        }
    }
    if(x!=1) pr[++tot]=x,ci[tot]=1;
    ll ret=1;
    for(int i=1;i<=tot;i++){
        ll nn=kuai(pr[i],(ci[i]-1));
        ret*=nn*(pr[i]-1);
    }
    return ret;
}
ll qm(ll a,ll b,ll p){
    ll ret=1,base=a;
    while(b){
        if(b&1) ret=(base*ret)%p;
        base=(base*base)%p;
        b>>=1;
    }
    return ret;
}
int gcd(int a,int b){
    return (b==0)?a:gcd(b,a%b);
}
int BSGS(ll a,ll b,ll c){
    //cout<<a<<" "<<b<<" "<<c<<endl;
    int up=(int)floor(sqrt(1.0*c-1))+1;
    ni[0]=1;
    int mi=fai(c);
    //cout<<"oula "<<mi<<endl;
    for(int i=1;i<=up;i++){
        ni[i]=qm(qm(a,i*up,c),mi-1,c);
    }
    for(int i=0;i<=up-1;i++){
        ll kk=qm(a,i,c);
        ha.insert(kk,i);
    }
    for(int i=0;i<=up;i++){
        ll bb=b*ni[i]%c;
        int kk=ha.find(bb);
        if(kk>=0) return i*up+kk;
    }
    return -233;
}
int EXBSGS(){
    int num=0;
    int yC=C;
    int yB=B;
    int yA=A;
    ll ji=1;
    int ret=-233;
     bool flag=false;    
    while(1){
        int g=gcd(A,C);
        //cout<<"gg "<<g<<endl;
        if(g==1) break;
        if(B%g) {
            flag=true;break;
        }
        B/=g,C/=g,ji=(ji*A/g)%C;
        num++;
    }
//    cout<<A<<" "<<B<<" "<<C<<endl;
    //cout<<" num "<<num<<endl;
    for(int i=0;i<=num;i++){
        ll kk=qm(yA,i,yC);
        //cout<<" kk "<<kk<<endl;
        if(kk%yC==yB) return i;
    }
    if(!flag){
        ll ni=1;
        ll mi=fai(C);
        ni=qm(ji,mi-1,C);
        ll NB=(B*ni)%C;
        ret=BSGS(A,NB,C);
    }
    if(ret>=0) return ret+num;
    else return -233;
}
int main(){
    while(1){
        scanf("%lld%lld%lld",&A,&C,&B);
        if(A==0&&B==0&&C==0) break;
        ha.init();
        B%=C;
        int ret=EXBSGS();
        if(ret>=0){
            printf("%d\n",ret);
        }
        else{
            puts("No Solution");
        }
    }
    return 0;
}
EXBSGS

 

BSGS&EXBSGS 大手拉小手,大步小步走

标签:sed   str   oid   i++   class   ace   ase   find   splay   

原文地址:https://www.cnblogs.com/Miracevin/p/9261234.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!