离散对数(例题+详解+代码模板)
生活随笔
收集整理的這篇文章主要介紹了
离散对数(例题+详解+代码模板)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
給定x,n,m,求x^y=n(mod m)的解(其中m是素數)
求解一個最小的x滿足給定的方程Bx?== N (mod P)
使用baby_step_giant_step算法。也就是先小步后大步算法。
1、令x=i*m+j ?(m=ceil(sqrt(p))),
那么原式化為 B^(i*m)*B^j==N(MOD P)
B^j==N*B^(-i*m)(MOD P)---------->B^j==N*B^m^(-i)(MOD P)
2、先預處理B^0,B^1,B^2……B^(m-1),存入HASH表,我使用結構體排序然后二分查找,這一步就是baby_step,每次移動1
3、然后快速冪求出B^-m,枚舉i,如果存在N*B^(-i*m)存在于HASH表中,說明存在解x=i*m+j,這一步為giant_step,每次移動m
注意以上解法是最基本的,只能對于gcd(B,P)==1,算法的時間復雜度是O(sqrt(P)*log(sqrt(P)))
模板:此模板m不一定非為質數
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #define ll long long using namespace std;ll b,n,p; /***************************************/下面就是BSGS的函數集,包括所需變量 const int N=100009; const int mod=76543; ll hs[N],id[N],head[N],next[N],tot; void insert(ll x,ll y) {int k=x%mod;hs[++tot]=x;id[tot]=y;next[tot]=head[k];head[k]=tot; } ll find(ll x) {int k=x%mod;for (int i=head[k];i;i=next[i])if (hs[i]==x) return id[i];return -1; } ll BSGS(ll a,ll b,ll n) {if (b==1) return 0;memset(head,0,sizeof(head));tot=0;ll j,m=sqrt(n*1.0),x=1,p=1;for (int i=0;i<m;i++,p=p*a%n) insert(p*b%n,i);for (ll i=m;i<=n;i+=m)if ((j=find(x=x*p%n))!=-1) return i-j;return -1; } /**************************************/ int main() {while(scanf("%lld%lld%lld",&p,&b,&n)!=EOF)//poj提交一定要有“!=EOF” !!!!!!!!!{ll ans=BSGS(b,n,p);if (ans==-1) printf("no solution\n");else printf("%lld\n",ans);} return 0; }總結
以上是生活随笔為你收集整理的离散对数(例题+详解+代码模板)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构实验之栈一:进制转换
- 下一篇: 语音基础知识-基本语音知识,声谱图,lo