POJ2417 Discrete Logging
Posted ljh2000
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ2417 Discrete Logging相关的知识,希望对你有一定的参考价值。
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
Description
B
L
== N (mod P)
Input
Output
Sample Input
5 2 1
5 2 2
5 2 3
5 2 4
5 3 1
5 3 2
5 3 3
5 3 4
5 4 1
5 4 2
5 4 3
5 4 4
12345701 2 1111111
1111111121 65537 1111111111
Sample Output
0
1
3
2
0
3
1
2
0
no solution
no solution
1
9584351
462803587
Hint
B
(P-1)
== 1 (mod P)
for any prime P and some other (fairly rare) numbers known as base-B pseudoprimes. A rarer subset of the base-B pseudoprimes, known as Carmichael numbers, are pseudoprimes for every base between 2 and P-1. A corollary to Fermat\'s theorem is that for any m
B
(-m)
== B
(P-1-m)
(mod P) .
Source
正解:BSGS算法
解题报告:
BSGS模板题。
BSGS又称大步小步算法(有人戏称之为拔山盖世算法),其实应该算是一种优化暴力,是一种用空间换时间的办法。
首先我们想对于$a^{x} \\equiv b$ ($mod p$),$a、b、p$已知,求最小的正整数$x$。不妨设 $m= \\sqrt{p} $ 取上整,令 $x=i*m+j$ ,那么我把原式化开之后就可以得到$a^{m*i}与b*a^{j}$关于p同余。对于右边值从$0$到$m$枚举$j$,把值插入哈希表,对于左边值从$1$到$m$枚举$i$,把值在哈希表中查询看是否存在,查询到的第一个答案即为所求。如果找不到的话,考虑因为我等于是枚举了$ a^{p} $以内的所有情况,但是还没有找到,根据费马小定理,指数大于$p$一定无解。
正确性的话应该是很好想通的,因为i枚举一开始就是$1$,乘上$m$之后显然一定比$b$大。
另外注意一点,因为插入哈希表时如果出现了相等的情况,显然$j$越大越好,所以j从小到大枚举时可以直接覆盖掉之前的结果。
//It is made by ljh2000 #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <algorithm> #include <ctime> #include <vector> #include <queue> #include <map> #include <set> #include <string> using namespace std; typedef long long LL; const int MOD = 300007; const int MAXM = 100000; LL p,b,ans,n,to[MAXM],next[MAXM]; int ecnt,first[MOD+12],block,w[MAXM]; inline LL gcd(LL x,LL y){ if(y==0) return x; return gcd(y,x%y); } inline LL fast_pow(LL x,LL y){ if(y==0) return 1; LL r=1; while(y>0) { if(y&1) r*=x,r%=p; x*=x; x%=p; y>>=1; } return r; } inline int getint(){ int w=0,q=0; char c=getchar(); while((c<\'0\'||c>\'9\') && c!=\'-\') c=getchar(); if(c==\'-\') q=1,c=getchar(); while (c>=\'0\'&&c<=\'9\') w=w*10+c-\'0\',c=getchar(); return q?-w:w; } inline void insert(LL x,int j){ LL cc=x; x%=MOD; for(int i=first[x];i;i=next[i]) if(to[i]==cc) { w[i]=j; return ; } next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=cc; w[ecnt]=j; } inline LL query(LL x){ LL cc=x; x%=MOD; for(int i=first[x];i;i=next[i]) if(to[i]==cc) return w[i]; return -1; } inline void work(){ bool ok; while(scanf("%lld",&p)!=EOF) { b=getint(); n=getint(); ans=0; if(n==1) { printf("0\\n"); continue; } if(gcd(b,p)!=1) { printf("no solution\\n"); continue; } memset(first,0,sizeof(first)); ecnt=0; block=sqrt(p); if(block*block<p) block++; for(int i=0;i<=block;i++) insert((n*fast_pow(b,i))%p,i); LL bm=fast_pow(b,block); ok=false; for(int i=1;i<=block;i++) { ans=query(fast_pow(bm,i)); if(ans==-1) continue; ok=true; printf("%lld\\n",(LL)i*block-ans); break; } if(!ok) printf("no solution\\n"); } } int main() { work(); return 0; }
以上是关于POJ2417 Discrete Logging的主要内容,如果未能解决你的问题,请参考以下文章
Discrete Logging POJ - 2417(BSGS)
POJ-2417-Discrete Logging(BSGS)
[POJ2417]Discrete Logging(指数级同余方程)