zoukankan      html  css  js  c++  java
  • BSGS学习记录/POJ 3696 The Luckiest number

    BSGS

    BSGS(baby-step giant-step),即大步小步算法。常用于求解离散对数问题。形式化地说,该算法可以在 (O(sqrt{p})) 的时间内求解

    [a^x equiv b pmod p ]

    其中 (aperp p)。方程的解 (x) 满足 (0 le x < p)。(在这里需要注意,只要 (aperp p) 就行了,不要求 (p) 是素数)

    算法描述

    (x = A left lceil sqrt p ight ceil - B),其中 (0le A,B le left lceil sqrt p ight ceil),则有 (a^{Aleft lceil sqrt p ight ceil -B} equiv b pmod p),稍加变换,则有 (a^{Aleft lceil sqrt p ight ceil} equiv ba^B pmod p)

    我们已知的是 (a,b),所以我们可以先算出等式右边的 (ba^B) 的所有取值,枚举 (B),用 hash/map 存下来,然后逐一计算 (a^{Aleft lceil sqrt p ight ceil}),枚举 (A),寻找是否有与之相等的 (ba^B),从而我们可以得到所有的 (x)(x=A left lceil sqrt p ight ceil - B)

    注意到 (A,B) 均小于 (left lceil sqrt p ight ceil),所以时间复杂度为 (Thetaleft (sqrt p ight )),用 map 则多一个 (log)

    上述介绍在CC BY-SA 4.0SATA条款下,转自OIWIKI

    P3846 [TJOI2007] 可爱的质数

    模板

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    unordered_map<ll,ll> mp;
    
    int main(){
    	ll p,a,b;
    	scanf("%lld%lld%lld",&p,&a,&b);
    	ll sqp=ceil(sqrt(p));//square root of p
    	ll rs=b,ap=1,ls=1;//rs/ls: right/left side
    	//ap: sqp-th power of a
    	for(int i=1;i<=sqp;++i){
    		rs=(rs*a)%p;
    		ap=(ap*a)%p;
    		mp[rs]=i;
    	}
    	for(int i=1;i<=sqp;++i){
    		ls=(ls*ap)%p;// ls=a^{i*sqrt{p}}
    		if(mp[ls]){
    			printf("%lld
    ",((i*sqp-mp[ls])%p+p)%p);
    			return 0;
    		}
    	}
    	puts("no solution");
    	return 0;
    }
    

    POJ The Luckiest number

    (underbrace{888 cdots88}_{ ext{x个}}equiv 0space (modspace L)最小的符合条件的正整数x).

    ((10^x-1) cdotfrac{8}{9}equiv0space(modspace L))

    (9n|8(10^x-1))

    (ecause gcd(8,9)=1,gcd(frac{n}{gcd(L,8)},frac{L}{gcd(L,8)})=1)

    ( herefore 10^xequiv1(modspace frac{9n}{gcd(L,8)}))

    注意到与此时x应严格大于0,在处理时,不能使 (x=A left lceil sqrt p ight ceil - B)(a^{Aleft lceil sqrt p ight ceil} equiv ba^B pmod p))的B不能为(left lceil sqrt p ight ceil),第一次循环处理到(left lceil sqrt p ight ceil-1).

    时间复杂度(O(sqrt L))

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<utility>
    using namespace std;
    typedef long long ll;
    #define N 150000
    ll hs[N],nxt[N],hd[N],val[N];
    ll cnt;
    
    void ins(ll x,ll v){
    	ll p=x%N;
    	hs[++cnt]=x;
    	val[cnt]=v;
    	nxt[cnt]=hd[p];
    	hd[p]=cnt;
    }
    
    ll fd(ll x){
    	ll p=x%N;
    	for(ll i=hd[p];i!=-1;i=nxt[i]){
    		if(hs[i]==x){
    			return val[i];
    		}
    	}
    	return -1;
    }
    
    ll __gcd(ll a,ll b){
    	return b==0?a:__gcd(b,a%b);
    }
    
    ll mul(ll a,ll b,ll c){
    	if(a<b){
    		swap(a,b);
    	}
    	ll ret=0,tmp=a;
    	while(b){
    		if(b&1){
    			ret+=tmp;
    			if(ret>=c) ret-=c;	
    		}
    		tmp<<=1;
    		if(tmp>=c) tmp-=c;
    		b>>=1;
    	}	
    	return ret%c;
    }
    
    int main(){
    	ll n;
    	ll cs=0;
    	while(scanf("%lld",&n),n){
    		cnt=0;
    		memset(hd,-1,sizeof hd);
    		ll p=9*n/__gcd(n,8ll),a=10,b=1;
    		if(__gcd(p,a)!=1){
    			printf("Case %lld: 0
    ",++cs);
    			continue;
    		}
    		ll sqp=ceil(sqrt((double)p));//square root of p
    		ll rs=b,ap=1,ls=1;//rs/ls: right/left side
    		//ap: sqp-th power of a
    		for(ll i=1;i<sqp;++i){
    			rs=(rs*a)%p;
    			ap=(ap*a)%p;
    			ins(rs,i);
    		}
    		if(sqp) ap=(ap*a)%p;
    		bool f=0;
    		for(ll i=1;i<=sqp;++i){
    			ls=mul(ls,ap,p);// ls=a^{i*sqrt{p}}
    			ll j;
    			if((j=fd(ls))!=-1){
    				f=1;
    				printf("Case %lld: %lld
    ",++cs,((i*sqp-j)%p+p)%p);
    				break;
    			}
    		}
    		if(!f){
    			printf("Case %lld: 0
    ",++cs);
    		}
    	}
    	return 0;
    }
    

    另外本题还有另一种解法

    易证:(aperp n, a^x equiv 1(modspace n))的最小整数解使(varphi(n))的约数,枚举约数即可。

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<utility>
    #include<iostream>
    using namespace std;
    typedef long long ll;
    
    ll __gcd(ll a,ll b){
    	return b==0?a:__gcd(b,a%b);
    }
    
    ll mul(ll a,ll b,ll c){
    	if(a<b){
    		swap(a,b);
    	}
    	ll ret=0,tmp=a;
    	while(b){
    		if(b&1){
    			ret+=tmp;
    			if(ret>=c) ret-=c;	
    		}
    		tmp<<=1;
    		if(tmp>=c) tmp-=c;
    		b>>=1;
    	}	
    	return ret%c;
    }
    
    ll qpow(ll a,ll b,ll c){
    	ll ret=1,tmp=a;
    	while(b){
    		if(b&1){
    			ret=mul(ret,tmp,c);
    		}
    		tmp=mul(tmp,tmp,c);
    		b>>=1;
    	}
    	return ret%c;
    }
    
    int main(){
    	ll n;
    	ll cs=0;
    	while(scanf("%lld",&n),n){
    		ll p=9*n/__gcd(n,8ll);
    		if(__gcd(p,10)!=1){
    			printf("Case %lld: 0
    ",++cs);
    			continue;
    		}
    		ll fai=p,t=p,r=sqrt(p);
    		for(ll i=2;i<=r;++i){
    			if(t%i==0){
    				fai=fai/i*(i-1);
    				t/=i;
    				while(t%i==0){
    					t/=i;
    				}	
    			}
    		}
    		if(t>1){
    			fai=fai/t*(t-1);
    		}
    		r=sqrt(fai);
    		ll ans=1e18;
    		bool f=0;
    		for(ll i=1;i<=r;++i){
    			if(fai%i==0){
    				if(qpow(10,i,p)==1){
    					ans=min(ans,i);
    					f=1;
    				}
    				if(qpow(10,fai/i,p)==1){
    					ans=min(ans,fai/i);
    					f=1;
    				}
    			}
    		}
    		printf("Case %lld: %lld
    ",++cs,f?ans:0);
    	}
    	return 0;
    }
    
  • 相关阅读:
    118/119. Pascal's Triangle/II
    160. Intersection of Two Linked Lists
    168. Excel Sheet Column Title
    167. Two Sum II
    172. Factorial Trailing Zeroes
    169. Majority Element
    189. Rotate Array
    202. Happy Number
    204. Count Primes
    MVC之Model元数据
  • 原文地址:https://www.cnblogs.com/chwhc/p/14523911.html
Copyright © 2011-2022 走看看