1.具有原根的数字仅有以下几种形式:,(p是奇质数)
2.一个数的最小原根的大小不超过
3.原根个数Φ(Φ(m))个,m为质数则原根个数Φ(m-1)
4.代码
5.应用 HDU5377 (准备另开一篇)
poj 1284 性质3质数的原根个数
1.定义
普通对数: 记做
离散对数就是把这个放在了模意义下,即求解方程: a^x≡b(mod p)
2.求解方法(扩展版BGBS 大步小步算法) 参考代码
这个模板用的二分,复杂度多个logn,有些模板用map或hash,hash可以根号n解决
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define Inf (1<<29)
#define LL long long
using namespace std;
const int MM=110;
const long long MOD=1000000007;
///扩展大步小步算法
struct baby///小步算法预存的结构体定义
{
long long b,j;
bool operator < (const baby &other)const{
if(b==other.b)return j0)
{
if(y&1)ans=(ans*x)%mod;
x=(x*x)%mod;
y>>=1;
}
return ans;
}
///小步预存的个数为m的结构体里面查找num
long long find(long long num,long long m)
{
long long l=0,r=m-1,ans=-1;
while(r>=l)
{
long long mid=(r+l)/2;
if(babyv[mid].b>=num){
if(babyv[mid].b==num)
ans=babyv[mid].j;
r=mid-1;
}
else l=mid+1;
}
return ans;
}
///A^x=B(modC)求解x,gcd(A,C)不一定等于1,无解返回-1
long long ex_babystep_giantstep(long long A,long long B,long long C)
{
for(long long i=0;i<=100;i++)///先在小于100的数里面测试
if(q_pow(A,i,C)==B%C)return i;
///消因子, 将A^x=B%C化为d*A^(x – n)=B%C
long long g,n=0,d=1;
while((g=gcd(A,C))!=1)
{
if(B%g)return -1;///无解
n++;
B/=g;
C/=g;
d=(d*A/g)%C;
}
///无扩展小步大步操作
long long m=ceil(sqrt(C)),ans=1;
for(long long j=0;j