数论-离散对数
Posted l-ly-03
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数论-离散对数相关的知识,希望对你有一定的参考价值。
首先要保证底数是原根,才有求解之说呐。
介绍一种BSGS(BabyStepGiantStep)算法,正如其名,走路分大步小步,相结合正是最好的方法。
小于$\sqrtp$的数打表保存,然后每次迈大步就好啦~
#include<iostream> #include<cstdio> #include<cmath> using namespace std; typedef long long i64; const int S=1e6+7; const int P=1e9+7; const int M=P-1; int bk; int f,c; int a; int h[S],p[S]; int pwr(int x,int a) int s=1; while(a) if(a&1) s=(i64)s*x%P; x=(i64)x*x%P; a>>=1; return s; void psh(int t,int x) int k=x%S; while(h[k]) ++k; if(k==S) k=0; h[k]=x; p[k]=t; int fnd(int x) int k=x%S; while(h[k]&&h[k]!=x) ++k; if(k==S) k=0; return h[k]?p[k]:-1; void init() bk=sqrt(P); int t=1; for(int i=0;i<bk;i++,t=(i64)t*c%P) psh(i,t); int gtlog(int x) int t=1,p,s=pwr(c,bk); for(int i=0;i<P;i+=bk,t=(i64)t*s%P) p=fnd((i64)x*pwr(t,P-2)%P); if(p!=-1) return i+p; int main() scanf("%d%d",&f,&c); if(pwr(c,P>>1)==1) printf("Error"); return 0; init(); a=gtlog(f); printf("%d\n",a); //cout<<pwr(c,a); return 0;
以上是关于数论-离散对数的主要内容,如果未能解决你的问题,请参考以下文章
恶补数论 Baby-Step-Giant-Step 大步小步求离散模对数