1. 程式人生 > >『基礎數論第三篇』

『基礎數論第三篇』

<前言>

整除
算術基本定理(唯一分解定理)
最大公約數和最小公倍數(gcd和lcm)
同餘
威爾遜定理和費馬小定理
尤拉函式以及求解
尤拉定理

<更新提示>

<第一次更新>這次基本上是最後一次數論更新啦,三篇部落格的內容已經基本涵蓋了普及組可能考到的所有內容,只有少數較難的內容可能會再次分析重提,基本知識點已經全啦。


<正文>

整除

定義

一個整數a能被另一個整數d整除,記作:d|a,意味著存在某個整數k,有a=kd。 0可被每個整數整除。若a>0且d|a,則|d|≤|a|。如果a|d,則我們稱d是a的倍數,a是d的約數。

性質

對於整除,有如下幾條重要的性質:
1 若d|a,則對於任意整數k有d|ka
2 若a|b且b|a,則有a=b ……對稱性
3 若c|b,b|a,則c|a ……傳遞性
4 若c|a,d|b,則cd|ab
5 若c|a,c|b,則c|(ma+nb)
6 若n∈N*,則(a-b)|(an-bn)。
7 若n為奇數,則(a+b)|(an+bn);
8 若n為偶數,則(a+b)|(an-bn)
9 任意n個連續正整數的乘積必能被n!整除

關於性質,我儘量給出說明或證明。

說明(證明)

1 顯然。
2 兩數互為倍數,顯然兩數相等。
3 設a=kb,因為c|b,由1得c|kb成立,即c|a。
4 a有因子c,b有因子d,所以ab有因子cd,即cd|ab。
5 由1推得
6,7,8 因式分解的基本公式,此處不再贅述
9 由組合數公式可得,
n

( n + 1 ) ( n +
2 ) . . . ( n + m 1 ) n ! \frac{n(n+1)(n+2)...(n+m-1)}{n!}
即意為n選m的方案數,顯然是個整數。如果需要嚴謹的證明,可以使用數學歸納法,嘗試用分數拆分的方法證明n=k成立時,n=k+1仍然成立。

例題:分解整數

一個正整數有時可以分解成若干連續正整數之和,如15=1+2+3+4+5,有時這種分解方法不止一種,如15還可以分解成4+5+6和7+8兩種,但有些正整數就不能分解,如16就不能分解。輸入正整數N,求出一個它的所有分解。
資料規模:N≤109

分析:
設可以分解的是a,a+1,…,b,即n=a+(a+1)+…+b,則n=(a+b)(b-a+1)/2,即(a+b)和(b-a+1)是2×n的一對因子。我們列舉2×n的所有因子,再解得a,b,檢查其是否合法即可。

程式碼如下:

#include<bits/stdc++.h>
using namespace std;
int n,t,flag=0;
int main()
{
	cin>>n;
	t=n*2;
	for(int i=sqrt(t*1.0);i>=2;i--)
	{
		int x,y;
		if(t%i==0)
		{
			x=i,y=t/i;

			if((x+y-1)%2==0)
			{
				int b=(x+y-1)/2;
				int a=x-b;
				if(a<=0||b<=0)continue;
				flag=1;
				for(int j=a;j<b;j++)
				{
					cout<<j<<" "; 
				}
				cout<<b<<endl;
			}
		}
	}
	if(!flag)cout<<"NONE"<<endl;
	return 0;
}

算術基本定理(唯一分解定理)

定義

任何一個大於1的自然數N,N都可以唯一分解成有限個質數的乘積,我們將其表示為如下的形式:
N = p 1 a 1 p 2 a 2 p 3 a 3 . . . p k a k N=p_1^{a_1}*p_2^{a_2}*p_3^{a_3}*...*p_k^{a_k}
其中p1 < p2 < p3 < … < pk ,其諸指數ai 為正整數。我們稱其為N的標準分解式。

證明

請原諒我證不來…
其存在性與唯一性的證明見此

公式

由算術基本定理引匯出的有兩個重要的公式如下:
1 N的正約數個數為:
( a 1 + 1 ) ( a 2 + 1 ) . . . ( a k + 1 ) (a_1+1)(a_2+1)...(a_k+1)

i = 1 n ( a i + 1 ) \sum_{i=1}^n{(a_i+1)}
2 N的正約數和為:
( 1 + p 1 1 + p 1 2 + . . . + p 1 a 1 ) ( 1 + p 2 1 + p 2 2 + . . . + p 2 a 2 ) . . . ( 1 + p k 1 + p k 2 + . . . + p k a k ) (1+p_1^1+p_1^2+...+p_1^{a_1})(1+p_2^1+p_2^2+...+p_2^{a_2})...(1+p_k^1+p_k^2+...+p_k^{a_k})

i = 1 n ( j = 0 a i p i j ) \prod_{i=1}^n(\sum_{j=0}^{a_i}p_i^j)

說明(證明)

1,2 由乘法原理推得。

程式碼實現

1 求N的分解質因數式

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int s=0,n,t;
    int ans[10000]={};
    cin>>n;t=n;
    for (int i=2;i*i<=n;i++)//相當與1-sqrt(n)列舉,這麼做可以處理複雜的精度誤差
        if (n%i==0)
        {
            while (n%i==0)
            {
                ans[++s]=i;//儲存分解質因子的答案
                n=n/i;//對n除以i,知道不能除為止 
            }   
        }   
    if (n>2)  ans[++s]=n;//若最後沒有分解完
    if(s==1)cout<<t<<'='<<ans[1];
    else if(s==2)cout<<t<<'='<<ans[1]<<'*'<<ans[2];
    else for(int i=1;i<=s;i++)
            {
                if(i==1)cout<<t<<'='<<ans[1]<<'*';
                else if(i==s)cout<<ans[s];
                else cout<<ans[i]<<'*';
            } 
    //輸出分解質因數的結果
    return 0; 
} 

2 求N的約數個數

int nums(int n)
{
int k, res, p;
 k=2; res=1;
 while (k*k<=a)
     {p=1; 
      while (n%k==0) {a/=k; p++; } 
      res*=p;
      k++;
     }
 if (a>1) res*=2; 
 return res;
} 

3 求N的約數和

int sum ( int n )
{
int k, res, tmp;
 k=2; res=1;
 while (k*k<=a)
    {tmp=1;
      while (n%k==0) {a/=k;tmp=tmp*k+1;}
      res*=tmp;
      k++;
    }
 if (a>1)  res*=(1+a);
 return res;
} 

最大公約數和最小公倍數(gcd和lcm)

定義

令a和b是不全為0的兩個整數,能使d|a和d|b的最大整數稱為a和b的最大公約數,用gcd(a,b)表示,或者記為(a,b)。
令a和b是不全為0的兩個整數,能使a|d和b|d的最小整數稱為a和b的最小公倍數,用lcm(a,b)表示,或者記為[a,b]

定理

1 ab = gcd(a,b) * lcm(a,b)
2,3
利用算術基本定理,設
a = p 1 a 1 p 2 a 2 . . . p k a k b = p 1 b 1 p 2 b 2 . . . p k b k a=p_1^{a_1}p_2^{a_2}...p_k^{a_k}\\b=p_1^{b_1}p_2^{b_2}...p_k^{b_k}
則有
g c d ( a , b ) = p 1 m i n ( a 1 , b 1 ) p 2 m i n ( a 2 , b 2 ) . . . p k m i n ( a k , b k ) l c m ( a , b ) = p 1 m a x ( a 1 , b 1 ) p 2 m a x ( a 2 , b 2 ) . . . p k m a x ( a k , b k ) gcd(a,b)=p_1^{min(a_1,b_1)}p_2^{min(a_2,b_2)}...p_k^{min(a_k,b_k)} \\ lcm(a,b)=p_1^{max(a_1,b_1)}p_2^{max(a_2,b_2)}...p_k^{max(a_k,b_k)}