数论
质数问题
-
定义:
一个正整数只有除1外和自身之外的任何自然数整除,则这个数称为质数,负责称为合数。
-
判定:
是为了判定n是不是质数;
根据定义可以知道只要找2~ n \sqrt{n} n之间有没有可以和n整除的就可以啦;
-
筛选
是为了找到1~N之间的所有质数;
任意的一个数,如x,它的倍数一点不是质数,所有从小到大扫,扫到一个数,把它的倍数标记为合数,就这样把所有的合数一点点的标记出来,而当扫到一个数未标记时,这个数就是质数;
memset(v,0,sizeof(v));//标记合数;
for(int i=2;i<=n;i++)
{
if(v[i]) continue;
cout<<i<<endl; // i是质数
for(int j=i;i<=n/i;j++) v[i*j]=1;
}
这个算法是Eratosthenes筛法,而时间复杂度=O(NloglogN);
- 质因数分解
定理:任何一个大于1的正整数都能唯一的分解为有限个质数的乘积,N= p 1 c 1 p 2 c 2 . . . p m c m p1^{c1}p2^{c2}...pm^{cm} p1c1p2c2...pmcm;
其中。ci都是正整数,pi都是质数。
约数
- 定义:
若整数n除以整数d的余数为0,即d能整除n,则称d是n的约数,n是d的倍数,记为d|n。
这是约数的推论;
- 约数集合
∵ \because ∵ d|n;
∴ \therefore ∴ d n ∣ \frac{d}{n}| nd∣n;
∴ \therefore ∴ d|n × \times ×n;
所以,只要扫描 1~ n \sqrt n n 就可以找到n的所有约数。
int factor[N] , tot = 0;
for( int i = 1 ; i * i <= n ; i ++ )
{
if( n % i ) continue;
factor[ ++ tot] = i;
if( i != n / i ) factor[ ++ tot ] = n / i;
}
最小公约数 最大公倍数
谈到最小公约数,就可以想到最大公倍数,所有我们就可以一起来写(因为有一些定理是有关二者的)
- 最大公约数
就是两个数的公共约数中最大的那个数;
int gcd(int a,int b)
{
if(a%b==0)
return b;
else
return gcd(a%b,b);
}
这是求两个数的gcd,(gcd是最大公约数),
九章 .更相减损术
a,b ∈ \in ∈N,a ≥ \ge ≥b, gcd(a,b)=gcd(b,a-b)=gcd(a,a-b);
a,b ∈ \in ∈N,有gcd(2a,2b)=2gcd(a,b);
最小公因数中,欧几里得算法;
:a,b ∈ \in ∈N,b ≠ \neq = 0, gcd(a,b)=gcd(b,a modb)
证明:
a可以表示成a = kb + r(a,b,k,r皆为正整数,且r<b),则r = a mod b
假设d是a,b的一个公约数,记作d|a,d|b,即a和b都可以被d整除。
而r = a - kb,两边同时除以d,r/d=a/d-kb/d=m,由等式右边可知m为整数,因此d|r
因此d也是b,a mod b的公约数。
因(a,b)和(b,a mod b)的公约数相等,则其最大公约数也相等,得证。
因为欧几里得算法我们才得以得出求解gcd的代码思想;
扩展欧几里得算法
定义: 对于任意整数a , b ,存在一对整数x , y ,满足a x + b y = g c d ( a , b ) ax+by=gcd(a,b)ax+by=gcd(a,b)
证明:
通过不断地应用公式 r k = r k − 2 − q k r k − 1 r_k = r_k−2 −q_kr_k−1 rk=rk−2−qkrk−1 可以求出可能为负数的 x,y,使得 r n = a x + b y 。 特 别 地 , 若 g c d ( a , b ) = 1 , 则 有 a x ≡ 1 ( m o d b ) , 即 x 为 a 模 b 的 逆 元 。 r_n = ax + by。 特别地,若 gcd(a,b) = 1,则有 ax ≡ 1 (mod b),即 x 为 a 模 b 的逆元。 rn