初等数论
线性筛
v数组记录每个数的最小质因子
CODE
int v[MAX_N],prime[MAX_N];
void primes(int n)
{
for (int i=2;i<=n;++i)
{
if (v[i]==0)//i是质数
{
v[i]=i;//i的最小质因子就是它本身
prime[++m]=i;
}
//给当前的数i乘上一个质因子
for (int j=1;j<=m;++j)
{
//i有比prime[j]更小的质因子,或者超出n的范围
if (prime[j]>v[i]||prime[j]>n/i) break;
//prime[j]是合数i*prime[j]的最小质因子
v[i*prime[j]]=prime[j];
//保证prime[j]比i的最小质因子小(或等于)
}
}
for (int i=1;i<=m;++i)
cout<<prime[i]<<endl;
}
素数定理
#1.唯一分解定理
任何一个大于1的正整数都能唯一分解为有限个质数的乘积
#2.费马小定理
p是质数,
ap≡a(modp)
a
p
≡
a
(
m
o
d
p
)
(当欧拉定理的n为p时)
或
p是质数,a、p互质,
ap−1≡1(modp)
a
p
−
1
≡
1
(
m
o
d
p
)
欧几里得算法
见这里
扩展欧几里得算法
见这里
BSGS(小步大步法)
Baby Step,Giant Step算法
问题:a,p互质,求一个整数x,使得
ax≡b(modp)
a
x
≡
b
(
m
o
d
p
)
解:把
b∗ajmodp
b
∗
a
j
m
o
d
p
插入一个Hash表。计算出
(at)imodp
(
a
t
)
i
m
o
d
p
,在Hash表中查找是否存在对应的j。
CODE
hash.end()表示指向空,所以无解
int baby_step_giant_step(int a,int b,int p)
{
map<int,int> hash;
hash.clear();
b%=p;
int t=(int)sqrt(p)+1;
for (int j=0;j<t;++j)
{
int val=(long long)b*power(a,j,p)%p;//b*a^j
hash[val]=j;//插入Hash表
}
a=power(a,t,p);//a^t
if (a==0) return b==0?1:-1;
for (int i=0;i<=t;++i)
{
int val=power(a,i,p);//(a^t)^i
//查找Hash表
int j=hash.find(val)==hash.end()?-1:hash[val];
if (j>=0&&i*t-j>=0) return i*t-j;
}
return -1;
}