2017清北學堂(提升組精英班)集訓筆記——基本數論

這是一個很大的專題同時也很重要,因此我十分再十分仔細地寫這個筆記,因此有點慢你們別介意。廢話很少說進入正題!php

1、數論(研究整數性質的東西):html

1.數論的分類(來自百度百科)ios

初等數論、解析數論、代數數論、幾何數論、計算數論、超越數論、組合數論、算術代數數論。c++

2.數算法

整數、天然數(大於等於0的整數)、正整數(大於0的整數)、負整數、非負整數、非正整數、非零整數、奇數 偶數。dom

3.Problem 3函數

設N爲奇數,a1,a2,…,aN爲1,2,…,N的一個排列,求證:(a1-1)(a2-2)…(aN-N)≡0(mod 2)。工具

證實:由於a1,a2,…,aN爲1,2,…,N的一個排列,因此a1+a2+…+aN=1+2+…+N,移項,得:(a1-1)+(a2-2)+…+(an-N)=0爲偶數,因此(a1-1),(a2-2),…,(an-N)中一定有至少一項爲偶數,因此(a1-1)(a2-2)…(an-N)爲偶數,即:(a1-1)(a2-2)…(aN-N)≡0(mod 2)。優化

4.整除性網站

設a,b∈Z,若是存在c∈Z而且a=bc,則稱b|a(b爲a的因子,「|」表示「能整除」)

5.質數

若是一個數,只有1和自身做爲因子的數,叫作質數(素數)。

通論1:存在一個質數p,若p|ab,則p|a或者p|b。

通論2:若p|a或者(p,a)=1(p和a的最大公因子爲1),則p|a能夠推出 p|a。

通論3:用π(x)表示不超過x的質數的個數,能夠證:limπ(x)lnx÷x=1,換種通俗說法就是:1~x的質數個數大約爲x/lnx(證實時間複雜度時能夠用)。

6.Problem 3.141

求證:當n爲合數時,2n-1爲合數。

證實:由於n爲合數,咱們能夠令n=ab,則2n-1=(2a-1)·(2n-a+2n-2a+2n-3a+…+2a+1),原式得證。

還能夠看出平方差公式是這個的一個特例。

7.質數的斷定

(1)一個不少人都在用的辦法(判斷一個較小的數是否爲質數):

1 bool prime(int x)//判斷質數 時間複雜度:O(sqrt(x)),最多1012~1014 
2 {
3     if(x<2) return false;
4     for(int a=2;a*a<=x;a++)
5     {
6         if(x%a==0) return false;//不是質數 
7     }
8     return true;//是質數 
9 }

(2)運用費馬小定理:

p爲一個素數且p不是a的倍數,則有:ap-1≡1(mod p)(不能從右邊推到左邊)

作法:屢次選取a檢驗p是否知足費馬小定理(說明p多是質數,選的知足條件的a越多,p爲質數的可能性越大)。

時間複雜度爲:O(klogp),選取k個a,判斷的過程用掉logp,總的加起來爲klogp。

特別地,這樣的算法有缺陷,由於有Carmichael數的存在,可致使上述算法給出一個錯誤的判斷,例如:56一、110五、1729,這三個數知足費馬小定理,可是它們都是合數

這裏給出1~10000的Carmichael數:56一、110五、172九、246五、282一、660一、8911。

(3)Miller-Rabin算法(判斷一個很大的數是否爲質數):

因爲Carmichael數的存在,而且Carmichael數是有無窮多個的,那怎麼辦?打表?確定不行啊!因此就要增強這個算法!

若是n爲素數,取a<n,令n-1=d×2r,則要麼ad≡1(mod n),要麼存在一個數i知足:0≤i<r,使得:ad×2^i≡-1(mod n),一個數mod n=-1」能夠表示爲:「一個數mod n=n-1」,一樣地也是不能從右邊推到左邊。

時間複雜度:O(klogn)

作法:屢次選取a檢驗p是否知足,則是質數的機率就大。(有個好消息:不存在Carmichael數這樣的特殊狀況!)

例如:12=3*22

 1 int a[5]={3,7,11,23,37}//這裏選了鍾神喜歡的5個質數來檢驗是否知足條件,若是不夠保險的話還能夠多加幾個 
 2 bool Miller_Rabin(int n)//從a[]中選出5個a 
 3 {
 4     n-1=d*2^r;//用n-1來肯定d、r
 5     for(int j=1;j<=5;j++)//這裏用了5個小於n的質數a來檢驗,用質數是由於效果更好!
 6     {
 7         if(pow(a[j],d)%n!=1)//不知足第一個條件,pow爲快速冪函數,pow(a,b)計算a^b 
 8         {
 9             for(int i=0;i<r;i++)
10             {
11                 if(pow(a[j],d*2^i)%n==-1) return true;//第二個條件 
12             }
13             return false;
14         }
15     } 
16 }

(4)篩法(處理1~n區間內有哪些質數):

基本作法:給出要篩數值的範圍sqrt(n),找出 sqrt(n)之內的素數p1,p2,p3,…,pk。先用2去篩,即把2留下,把2的倍數剔除掉;再用下一個素數,也就是3篩,把3留下,把3的倍數剔除掉;接下去用下一個素數5篩,把5留下,把5的倍數剔除掉;這樣不斷重複下去……

①非線性篩法;

1 bool not_prime[1000000];//true表示不是質數,false表示是質數 
2 not_prime[1]=true;//1不是質數 
3 for(int a=2;a<=n;a++)
4 {
5     for(int b=a+a;b<=n;b+=a)
6     {
7         not_prime[b]=true;
8     }
9 }

時間複雜度:(1/1+1/2+1/3+1/4+…+1/n)*n=nlogn

下面給出了優化版篩法,時間複雜度爲:nlog(logn)

算法思路:若是當前這個數是合數,以前已經枚舉過比它小的因子,在枚舉這個小因子的時候,已經把這個合數的倍數覆蓋掉了,因此不必。

 1 bool not_prime[1000000];//優化版非線性篩法 
 2 not_prime[1]=true;//1不是質數 
 3 for(int a=2;a<=n;a++)
 4 {
 5     if(!not_prime[a])//若是是質數,進入循環,是合數就不進入 
 6     {
 7         for(int b=a+a;b<=n;b+=a)
 8         {
 9             not_prime[b]=true;
10         }
11     }
12 }

②線性篩法:

算法思路:每一個合數都由它最小的質因子篩掉(代碼第12行)。一個合數會被拆成幾個質因子相乘,利用最小的質因子就能夠把這個合數篩掉了,避免了重複篩的過程。

 1 int not_prime[1000000];
 2 int prime[1000000];//質數表 
 3 int prime_count=0;//質數的個數 
 4 memset(not_prime,0,sizeof(not_prime));
 5 not_prime[1]=true;//1不是質數
 6 for(int i=2;i<=n;i++)
 7 {
 8     if(!not_prime[i]) prime[++prime_count]=i;//把i放入質數表prime[]中 
 9     for(int j=1;j<=prime_count;++j)//枚舉質數表中的每個數 
10     {
11         if(prime[j]*i>n) break;
12         not_prime[prime[j]*i]=true;//翻倍,一個數×另外一個數必定爲合數 
13         if(i%prime[j]==0) break;
14     }
15 } 

時間複雜度:是線性的,接近於O(n)。

8.最大公因數

(1)歐幾里得算法(展轉相除法):

原理什麼的我就不說了,看代碼YY一下就知道啦(詳見人教版高中數學必修三)。

1 int gcd(int a,int b)//歐幾里得算法 時間複雜度:O(loga) 
2 {
3     if(!b) return a;
4     else return gcd(b,a%b);
5 }
6 int gcd(int a,int b)//簡化版歐幾里得算法 時間複雜度:O(loga) 
7 {
8     return b?gcd(b,a%b):a;//一行代碼就是爽 
9 }

(2)擴展歐幾里得算法:

用來在已知的a、b中求解一組x、y,使得ax+by=gcd(a,b)成立(根據數論相關定理,這組解必定存在)

求解過程(引自P2O5 dalao的blog:http://p2oileen.xyz/index.php/2017/06/07/exgcd/

設a>b,則有當b=0時,gcd(a,b)=a,此時x=1,y=0。

當ab≠0時,設ax1+by1=gcd(a,b),由於gcd(a,b)=gcd(b,a%b),則必定有:bx2(a%b)y2=gcd(b,a%b)=gcd(a,b)=ax1+by1

因此將bx2+(a%b)y2=ax1+by1移項+整理可得:

ax1+by1=bx2+(a-(a/b)*b)y2=ay2+bx2-(a/b)*by2;

根據恆等定理:x1=y2; y1=x2-(a/b)*y2;

這樣咱們就能夠經過x2,y2遞歸求解x1,y1辣!

在gcd不斷遞歸求解的過程當中,總會有一個時刻b=0,因此遞歸是有終止條件的。

遞歸代碼以下:

 1 int Ex_Gcd(int a,int b,int &x,int &y)
 2 {
 3     if(b==0)
 4     {
 5         x=1;
 6         y=0;
 7         return a;
 8     }
 9     int ans=Ex_Gcd(b,a%b,x,y);
10     int t=x;
11     x=y;
12     y=t-a/b*y;
13     return ans;//返回a、b的最大公約數 14 }

9.中國剩餘定理(求解一次同餘式組)

原問題:有物不知其數,三三數之剩二,五五數之剩三,七七數之剩二,問物幾何?

簡單地來講:有一個數x≡a1(mod p1),x≡a2(mod p2),x≡a3(mod p3),…,x≡ak(mod pk),求解一個最小的x。

根據問題,咱們能夠得出好多好多好多的方程:

x=k1p1+a1x=k2p2+a2……

兩個方程爲一組,解之:

k1p1+a1=k2p2+a2移項得:k1p1-k2p2=a2-a1

在咱們小學的時候,就接觸了一個這樣的解法,很簡單很實用,如今就來模擬一下!

大數翻倍法(一種求解最小公倍數的方法)

舉個栗子:

如要求兩個數的最小公倍數,則將較大數翻倍,一直翻倍到是較小數的倍數時那麼這個數就是這兩個數的最小公倍數。
如:6和7
7×1=7,7×2=14,7×3=21,7×4=28,7×5=35,7×6=42
42是6的倍數,那麼42就是6和7的最小公倍數。
這個算法的基本思想就是:找到一個最大的ans,而後不斷翻倍,使它可以整除其餘全部的p
咱們假設p1<p2,有:
1 //大數翻倍法 時間複雜度:O(min(p1,p2)) 
2 int fanbei(int a1,int p1,int a2,int p2)//p1<p2
3 {
4     ans=a2;
5     while(ans%p1!=a1) ans=ans+p2;
6     return ans;
7 }

根據ans=a2+p1p2≡a2(mod p1),計算得出時間複雜度爲O(min(p1,p2)),也就是說加p1次必定會找到一個解!

10.逆元

定義:若是gcd(a,m)=1且存在惟一的b使得a×b≡1(mod m)且1≤b<m,則b爲a在模m意義下的逆元,a、b互爲逆元。

舉個栗子:令a=3,m=7,咱們但願找到一個b知足a×b≡1(mod m)且1≤b<m,不難找到b=5。則5爲3在模7意義下的逆元,三、5互爲逆元。

逆元的做用:在模的意義下作除法,舉個栗子:計算(3×6÷3)mod7的結果,按照通常的順序能夠算出原式=(18÷3)mod7=6mod7=6。咱們利用模的性質,能夠把原式變爲:(((3×6)mod7)÷3)mod7=4÷3mod7。咱們發現進行到這裏就沒法計算了(模意義下不能作除法),這時候就要用到逆元,3的逆元爲5,因此原式"4÷3mod7"變爲"4×5mod7",計算得6。

尋找逆元的方法

①費馬小定理:ap-1≡1(mod p),p爲質數,求a的逆元(保證a和p互質)?

兩邊同除以a得:ap-2≡1/a(mod p),也就是說,任意一個數a在模質數p意義下的逆元就是ap-2

②歐拉定理:aφ(m)≡1適用於任何數m,但要保證gcd(a,m)=1,解法和費馬小定理相同,φ(m)的意義以後會講

11.積性函數

定義:若是對於gcd(n,m)=1,有f(nm)=f(n)f(m),則稱f爲積性函數,例如f(x)=1就是積性函數。

給出一些經典的積性函數:

①σ(n)=Σd|nd:n的全部因子之和

②τ(n)=Σd|n1:n的因子個數

③μ(n)莫比烏斯函數,稍後會講(詳見13點)

④φ(n)歐拉函數:1~n當中與n互質的數的個數,例如φ(6)=2,下面介紹用大約O(n2)的方法求1~n的全部數的φ(ai):

假設一個數n,求φ(n)?由於n=P1k1·P2k2·…·Prkr → φ(n)=n·(P1-1)/P1·(P2-1)/P2·…·(Pr-1)/Pr

舉兩個例子:

30=2*3*5,因此φ(30)=30*(1/2)*(2/3)*(4/5)=8。

160=25*5,因此φ(160)=160*(1/2)*(4/5)=64。

講了這麼多的函數,怎麼樣用到積性的性質呢?

積性的意義在於:能夠在O(n)的時間複雜度內,求出1~n全部數的函數值。

以下的例子(運用在歐拉函數):咱們在O(n)的時間內求出1~n全部數的φ值

要用到線性篩(其餘的函數也是差很少——線性篩中加上函數便可)!

 1 memset(notprime,0,sizeof(notprime)),notprime[1]=true;//初始化 
 2 phi[1]=1;//賦初值,φ(1)=1 
 3 for(int i=2;i<=n;i++)
 4 {
 5     if(!notprime[i])//是質數 
 6     {
 7         prime[++prime_count]=i;
 8         phi[i]=i-1;//若是i是質數,顯然和i互質的數有i-1個 
 9     }
10     for(int j=1;j<=prime_count;++j)//求合數的φ 
11     {
12         if(prime[j]*i>n)//考慮prime[j]*i這個合數 
13         {
14             break;
15         }
16         not_prime[prime[j]*i]=true;
17         /*根據積性函數定義,有φ(prime[j]*i)=φ(prime[j])*φ(i),要用積性函數的性質,必須知足prime[j]和i互質*/
18         if(i%prime[j]!=0)//prime[j]和i互質 
19         {
20             phi[prime[j]*i]=phi[prime[j]]*phi[i];//直接利用積性函數性質
21         }
22         else//i是prime[j]的倍數(不互質)
23         {
24             phi[prime[j]*i]=prime[j]*phi[i];
25             /*把prime[j]*i分紅prime[j]段,每段長度爲i,那麼每一段與i互質的數同樣多,根據性質:若a與b互質,那麼a+b與b互質,a+2b與b互質,因此在第一段和i互質的數加上i以後還和prime[j]互質,因此整個裏面就有prime[j]*phi[i]個數和它是互質的,因此phi[prime[j]*i]=prime[j]*phi[i]*/
26         }
27         if(i%prime[j]==0) break;
28     }
29 } 

12.卷積(這個我是真的不懂)

f*g=Σd|nf(d)g (n/d)

13.莫比烏斯

(1)莫比烏斯函數:

含義(三種狀況):拆解一個數n=P1k1*P2k2*P3k3*…*Prkr

①若n=1,μ(n)=1 ②當k1=k2=k3=…kr=1時,μ(n)=(-1)r ③前面兩個條件都不知足時,μ(n)=0。

意義:容斥原理必備,多有使用到的地方,但願考慮一下吧。

(2)莫比烏斯反演:

如下兩個條件等價:

①對於任意正整數n,f(n)=Σd|ng(d)

②對於任意正整數n,g(n)=Σd|nμ(d)f(n/d)

14.一些東西

①Σd|nφ(d)=n:一個數的因子的φ加起來等於n。

②Σd|nμ(d)=[n=1]:若是n=1,則n的全部因子的μ值和爲1,不然爲0。

15.歐拉定理

費馬小定理的推廣:aφ(m)≡1(mod m)。

補充一些同餘的性質:

①反身性:a≡a(mod m)

②對稱性:若a≡b(mod m),則b≡a(mod m)

③傳遞性:若a≡b(mod m),b≡c(mod m),則a≡c(mod m)

④同餘式相加:若a≡b(mod m),c≡d(mod m),則a±c≡b±d(mod m)

⑤同餘式相乘:若a≡b(mod m),c≡d(mod m),則ac≡bd(mod m)

經典例題:給定數a、b、p,求ax≡b(mod p)的最小正整數解x。

BSGS算法——「北上廣深算法」或「拔山蓋世算法」:

令x=im-j,m=⌈sqrt(p)⌉,則aim-j≡b(mod p),

移項,有:(am)i≡baj(mod p)

首先,從0~m枚舉j,將獲得的baj的值存入hash表;

而後,從1~m枚舉i,計算(am)j,查表,若是有值與之相等,則當時獲得的im-j是最小值。

 1 #include<iostream>  
 2 #include<cstdio>  
 3 #include<cstring>  
 4 #include<algorithm>  
 5 #include<map>  
 6 #include<cmath>   
 7 using namespace std;  
 8 long long a,b,c,m,f[10000000];  
 9 map<long long,int> mp;  
10 long long qsm(long long x)  //快速冪
11 {  
12     long long sum=1; 
13     long long aa=a;   
14       while(x>0)  
15     {  
16         if(x&1)  
17         sum=(sum*aa)%c;  
18         x=x>>1;  
19          aa=(aa*aa)%c;  
20     }  
21     return sum;  
22 }  
23 int main()  
24 {  
25     mp.clear();//刪除map中的全部元素。
26     while(scanf("%lld%lld%lld",&c,&a,&b)!=EOF)  
27     {
28         mp.clear();  
29         if(a%c==0)//判斷a,c 是否互質,由於c 是質數,因此直接判斷是否整除便可
30         {  
31             printf("no solution\n");  
32             continue;  
33         }  
34         int p=false;  
35         m=ceil(sqrt(c)); 
36         long long ans;  
37         for(int i=0;i<=m;i++)  
38         { 
39             if(i==0)
40             {
41                   ans=b%c; 
42                 mp[ans]=i; 
43                   continue;
44             }
45             ans=(ans*a)%c;    
46             mp[ans]=i;  
47         } 
48         long long t=qsm(m); 
49         ans=1;
50         for(int i=1;i<=m;i++)  
51         {  
52               ans=(ans*t)%c;  
53             if(mp[ans])  
54             {  
55                 int t=i*m-mp[ans];  
56                 printf("%d\n",(t%c+c)%c);  
57                 p=true;  
58                 break;  
59             }  
60         }  
61         if(!p)
62         {
63             printf("no solution\n");  
64         }       
65     }  
66 }  

經典例題:求[l,r]之間的全部素數,1≤l≤r≤109,r-l≤105

三個解法:

①Miller-Rabin

②線性篩

③SPOJ PRIME1

2、機率:

一些定義和推論

①Pr[i]表示事件i發生的機率

②Pr[1]+Pr[2]+…Pr[N]=1

③xi表示事件i的權重(本身定義的權重)

④事件xi的指望E[xi]=Pr[i]×xi(i:1~N)  指望=機率×權重

⑤對於獨立事件i和j,Pr[i^j]=Pr[i]×Pr[j],事件i和j的指望是可加的

⑥當事件j已經發生時,事件i發生的機率爲:Pr[i|j]=Pr[i^j]/Pr[j]

一個有趣的結論:當太陽已經從東邊升起N天后,第N+1天從東邊升起的機率:(N+1)/(N+2)。

1.Problem 1

在小蔥和小澤面前有三瓶藥,其中有兩瓶是毒藥一瓶是可樂,每一個人必須喝一瓶。

小蔥和小澤各自選了一瓶藥,小澤手速比較快將藥喝了下去,而後就掛掉了。

小蔥想活下去,他是應該喝掉手上這瓶藥,仍是喝掉另一瓶呢?

咱們把瓶子編號爲一、二、3,一、2號藥是毒藥,3號藥是可樂。

根據全排列的知識,咱們列出6種狀況:

一、二、3;一、三、2;

二、一、3;二、三、1;

三、一、2;三、二、1;

因爲第一我的是被毒死了,因此只多是一、二、3;一、三、2;二、一、3;二、三、1;這四種狀況,咱們發現第二我的喝的是解藥的機率爲:Pr[是解藥]=(1+1)/4=50%。

更簡單的想法:小蔥選哪一個都同樣,由於小蔥不知道哪一個是毒藥哪一個是可樂。

鍾神:顯然無所謂!

2.淺談瑪麗蓮問題

美國某娛樂節目的舞臺上,臺上有三個門,其中一個門後邊有汽車,另外兩個門後邊是山羊,主持人讓你任意選擇其中一個,而後他打開其他兩個門中的一個,你看到的是山羊,這時,主持人會讓你從新選擇,那麼你會堅持原來的選擇仍是換選另一個未被打開過的門呢?

分兩種狀況討論:

①不換門:抽中汽車的機率是1/3。

②換門:咱們編號三個門分別爲一、二、3,分別對應羊、羊、車

狀況1:假設你第一次猜的那個門是1,主持人必將打開2,選擇換門3必能獲得車。

狀況2:假設你第一次猜的那個門是2,主持人必將打開1,選擇換門3必能獲得車。

狀況3:假設你第一次猜的那個門是3,主持人會打開1或2,你會換1或2號門,得不到車。

綜上所述:換門抽中汽車的機率爲2/3。

Pr(換門)>Pr(不換門),因此應該換門!

如今思考:一樣是二選一,爲何機率會不一樣?

由於主持人知道哪一個門是羊哪一個門是車,上一題中小蔥不知道哪瓶是毒藥,由於主持人從中做祟,因此機率不一樣!

3.Problem 2

小胡站在原點,手裏拿着兩枚硬幣。拋第一枚硬幣正面向上的機率爲p,第二枚正面向上的機率爲q。

小胡開始拋第一枚硬幣,每次拋到反面小胡就向x軸正方向走一步,直到拋到正面。

接下來小胡繼續拋第一枚硬幣,每次拋到反面小胡就向y軸正方向走一步,直到拋到正面。

如今小胡想回來了,因而他開始拋第二枚硬幣,若是小胡拋到正面就向x軸的負方向走一步,不然小胡就向y軸的負方向走一步。

如今小胡想知道他在往回走的時候通過原點的機率是多少?

根據定理:往x軸走k步的機率爲(1-p)x×p,同理於y軸。

咱們能夠枚舉小胡在第一輪中走到的點(x,y)

小胡走到點(x,y)的機率爲(1-p)x+y×p2(乘法原理)

小胡從點(x,y)走回原點的機率爲qx×(1-q)y×[(x+y)!/(x!×y!)]。

說明:qx×(1-q)y表示前幾步都走x步,後幾步都走y步的機率,而實際狀況是能夠交替着走的,因此咱們在後面乘上(也就是[(x+y)!/(x!×y!)]),才能表示從兩種狀況中選擇往x、y之一走的機率。

因此最終的機率爲(對全部狀況進行求和):

這個式子很很差求啊!!肆意展現一下數學功底的時候到了!

咱們改變枚舉量進行化簡!過程以下:

其中:

說明:在以上的推理過程當中,打"*"的這一步和紅框的推理過程:

①打紅框這一步推理:

根據二項式定理,有(字醜不要介意;′⌒`):

類比一下,有a=q,b=(1-q),因此原式能夠化簡爲(q+1-q)i=1i=1(太™聰明瞭啊!!)

打"*"這一步推理:

直接是等比數列求和便可!

4.Problem 2.333333

小蔥想要過河,過河有兩條路:

一條路有100個石頭,每一個石頭有1/100的機率會掛掉。

另外一條路有1000個石頭,每一個石頭有1/1000的機率會掛掉。

小蔥應該走哪條路呢?(請勿使用計算器)

5.Problem 3(這道題太醜被丟掉了)

小蔥在平面上畫了不少條平行等間距爲l的直線,小蔥將長度爲1的針投到這個平面上,求針和直線相交的機率?

典型的蒲豐投針問題:

分狀況討論:

①當l≤1:

當l>1:

6.Problem 4

小澤在數軸上的0點處,他每次有r的機率向右走,有1-r的機率向左走,求小澤走到-1處的機率爲?

解法:若是直接列式求和計算:大量組合數求和!卡特蘭數!級數!(mmp看得我想死)

設到達x-1的機率爲p,則p=(1-r)×1+r×p×p 第一步向左走到-1的機率+第一步向右走回到-1的機率(往左走兩次到-1)

根據上式,變形得:rp2-p+1-r=0,解方程可獲得:p=(1±|2r-1|)/2r,由於有絕對值,因此分類討論2r和1的關係:

通過緊張又激烈的討論,咱們得出一個分段函數(r均可以取):

7.Problem 5

小胡有一棵一個點的樹,小胡會給這個點澆水,因而這個點會有𝑝的機率長出兩個兒子節點。
每次長出新的節點以後,小胡又會給新的節點澆水,它們也都有𝑝的機率長出兩個新的兒子節點。
小胡不但願本身被累死,因此小胡但願知道這棵樹的大小是有限的的機率。

解法:這道題和上一題是一毛同樣的!

8.經典題1

給出n行m列矩陣,k次操做,每次操做選取一個子矩陣,子矩陣內的全部矩陣標記,作了k次操做內,被重複標記的標記爲已標記。

求:k次操做後,對於左上角座標爲(x,y)的矩形,至少被1個子矩陣包含的機率爲多少?

例如:下面一個2×2的矩陣:

當k=1時,有9種標記方法:

而咱們總共可以標記1×4+2×4+4×1個矩陣,因此獲得的機率爲1/9×(1×4+2×4+4×1)=16/9。

推理過程

假設k=1時,咱們來觀察一個3×4的矩陣:

 

要使得A包含這個紅色的矩陣B,那麼這個矩陣A的左上點和右下點應該在藍色的區域,這樣才能保證徹底覆蓋紅色矩陣

假設這個矩陣的左上的點爲(x,y),右下的點爲(n-x+1,m-y+1),在這個圖形裏面總共有:(1+2+3+…+n)=[n×(n+1)×m×(m+1)]/(2×2)個矩陣,而且知足藍色文字的條件後,矩陣一共有:x×y×(n-x+1)×(m-y+1)個,因此機率爲:x×y×(n-x+1)×(m-y+1)/{[n×(n+1)×m×(m+1)]/(2×2)}。

9.經典題2

有n個點,座標爲(x1,y1),(x2,y2),(x3,y3),…,(xn,yn),求一個圓,包含這全部的點,而且保證半徑最小。

暴力解法:枚舉三個點,算出圓,把剩下的點所有丟進去判斷在不在裏面,算法複雜度:O(n4)

優化暴力解法O(n3)

 1 for(int a=1;a<=n;a++)//往已知圓內一個一個地丟點 
 2 {
 3     if(!in(p[a])) circle=cir(p[a]);//a不在圓內 
 4     circle=cir(p[a]);//構造以a位圓心的圓 
 5     for(int b=1;b<=a;b++)
 6     {
 7         if(!in(p[b])) circle=cir(p[a],p[b]);//構造以a、b兩點爲直徑的圓 
 8         for(int c=1;c<=b;c++)
 9         {
10             if(!in(c)) circle=cir(p[a],p[b],p[c]);//構造a、b、c三點共圓的圓 
11         }
12     }
13 }

最優雅地優化O(n):利用C++中的一個函數叫:random_shuffle(隨機打亂n個點的順序),能夠將時間複雜度優化到O(n),怎麼樣?很神奇很詭異吧??!

思想就是:隨機選三個點造成一個圓,因而接下來的那些的點進入下面兩個for循環的機率實際上很小!

3、代數:

來一些概念!代數的重要性…

最強大的計算工具

最基本的數學知識

近世代數的貢獻

三大不可尺規做圖問題

五次及以上的方程沒有根式解

同構問題的計數

近代以及現代的加密技術

1.排列和逆序對

排列的定義:通常地,從n個不一樣元素中取出m(m≤n)個元素,按照必定的順序排成一列,叫作從n個元素中取出m個元素的一個排列,當n=m時,這個排列被稱做全排列。

逆序對的定義:τ,設A爲一個有n個數字的有序集(n>1),其中全部數字各不相同,若是存在正整數i,j 使得1≤i<j≤n而且A[i] >A[j],則<A[i],A[j]>這個有序對稱爲A的一個逆序對,也稱做逆序數。例如τ(3,1,2)=2。

對換的定義:在一個排列中,對換其中某兩個數,其他的數不動,獲得另外一個排列,這種操做稱爲一個對換。

奇偶排列的定義:若是一個排列的逆序數是偶數,則稱此排列爲偶排列,不然稱爲奇排列。

定理:對換改變排列的奇偶性。

定理:在所有的n階(n≥2)排列中,奇偶排列各佔一半。

定理:任意一個排列可通過一系列對換變成天然排列,而且所做對換次數的奇偶性與這個排列的奇偶性相同。

2.行列式(我不知道這玩意兒怎麼用)

定義:N階行列式是由N2個數aij(i,j=1,2,…,n)經過下式肯定的一個數

也稱爲行列式的徹底展開式。

sgn(j1j2…jn)=(-1)τ(j1j2…jn)=

一些引理

①行列互換,值不變。

②用一個數乘行列式的某行等於用這個數乘此行列式。

③若是行列式中某一行是兩組數之和,則這個行列式等於兩個行列式之和,這兩個行列式分別以這兩組數爲該行,而其他各行與原行列式對應各行相同。

④對換行列式中兩行的位置,行列式爲反號。

⑤若是行列式中有兩行成比例,則行列式等於0。

⑥把一行的某個倍數加到另外一行,行列式的值不變。

3.Cramer法則

若是線性方程組:

則線性方程組有惟一解xj=Dj÷D(j=1,2,…,n)。

其中:

證實思路:先證實是解,再證實惟一性。

引理

①若齊次線性方程組:

則方程只有零解。

②若是齊次線性方程組有非零解,則係數行列式必爲零。

4.通常線性方程組

定義①:通常線性方程組:

定義②:方程組的全體解稱爲方程組的解集合。

定義③:兩個有相同解集合的方程組稱爲同解方程組。

定義④:線性方程組的初等變換(把一個方程組變爲同解方程組):

<1>用一個非零數乘以某個方程。

<2>將一個方程的k倍加到另外一個方程上。

<3>交換兩個方程的位置。

定義⑤:係數矩陣:

定義⑥:增廣矩陣:

定理:對n元非齊次線性方程組的增廣矩陣實行高斯消元法,獲得階梯型矩陣:

5.高斯消元法

思想:變成上三角矩陣!

若是dr+1≠0,方程組無解。

若是dr+1=0,方程組有解。

當r=n時,有惟一解。

當r<n時,有無窮多解。

高斯消元法舉例詳解

咱們先來看一個例子:

一個方程組:

運用高斯消元,把未知數前的係數和常數列出n×(n+1)的矩陣以下:

咱們按照通常的解方程思路,確定先想到消去x1,即②-①,③-①得:

而後再消去x2,即:③-②×3得:

而後咱們保留除最後一列前面的矩陣:

這時,咱們獲得了一個上三角矩陣(說明有解,若不能化爲上三角矩陣,則無解)!咱們就能夠直接用高斯消元。

∴觀察獲得的矩陣:x3=21/2,x2=3-2x3=-18,帶入x3、x2便可求解得x1

一個小小的問題:咱們一直沒有用到最後一列,那要算這一列幹啥呢?這是用來方便計算答案的,也就是在構成上三角矩陣後直接利用最後一列的值計算便可(也就是下劃線那步)

再來看一個特例方程組:

按照上題的步驟,咱們獲得一個矩陣:

觀察第一行,第一個數是0,不方便消元,因此咱們往下找行,直到找到第一個數不是0爲止,而後交換這兩行,以後咱們就能夠開始消元了。

注意:對於第一個例子中的藍色的"3「怎麼得?咱們是這樣理解的:其實上面的運算"②-①","③-①"中,省略了"×1"這個項。咱們假設後面的這個項是a,那麼a=m[b][a]/m[a][a](m爲矩陣),意思是第b個方程的xa的係數÷第a個方程的xa的係數。

要變成上三角矩陣,就要化簡,咱們用做爲例子,要保證第一行前面0個0,第二行前面有1個0,第三行前面有2個0,以此類推…,因此咱們用這行第一個不是0的數÷第一行這一列的數獲得這個項便可獲得a。

高斯消元代碼(修改版,引用自P2O5 dalao:https://zybuluo.com/P2Oileen/note/816892#%E8%A1%8C%E5%88%97%E5%BC%8F):

 1 void gauss()//時間複雜度:O(n^3) 
 2 {
 3     //矩陣:m
 4     for(int a=1;a<=n;a++)
 5     {
 6         if(fabs(m[a][a])<=eps)
 7         {
 8             for(int b=a+1;b<=n;b++)//eps=10^-9 
 9             {
10                 if(fabs(m[b][a])>eps) swap(m[a],m[b]);//fabs用於浮點數,m[a],m[b]是引用//此處有問題,請大佬指正
11                 break;
12             }
13         }
14         for(int b=a+1;b<=n;b++)
15         {
16             ratio=m[b][a]/m[a][a];
17             for(int c=1;c<=n+1;c++)//c能夠從a開始循環 
18             {
19                 m[b][c]-=m[a][c]*ratio;
20             }
21         }
22     }
23     for(int a=n;a>=1;a--)
24     {
25         solution[a]=m[a][n+1];
26         for(int b=a+1;b<=n;b++)
27         {
28             solution/=m[a][a];
29         }
30     }
31 }

舉個栗子:
f(x)=ax5+bx4+cx3+dx2+ex+f
能夠獲得f(1),f(2),f(3),f(4),f(5),f(6),而後利用高斯消元法就能夠解決這個問題了。

高斯消元法自動找規律機

(1)用高斯消元法打表。

(2)枚舉次數,符合表就是正確答案。

6.矩陣

定義:由mn個數排列成m行n列矩陣的數表

稱爲一個m×n的矩陣,記作A。其中aij稱爲第i行第j列的元素。

一些特殊的矩陣種類

①零矩陣0:全部元素都是0的矩陣。

②對角矩陣:主對角線(左上到右下)之外的數都爲0的矩陣。

③單位矩陣I:矩陣對角線上都是1,其他爲0。

④純量矩陣:A=diag(c,c,…,c)。

⑤上三角矩陣:上半部分有值,例如:

⑥下三角矩陣:下半部分有值,例如:

⑦對稱矩陣,例如:

⑧反對稱矩陣

一些定義

矩陣的相等:每一個位置上的數相等。

矩陣的加法:兩個矩陣對應位置元素相加。

矩陣的數量乘法:一個數乘以一個矩陣,矩陣中的每一個元素都和這個元素相乘。

矩陣的乘法:設矩陣A=(aij)m×r,矩陣B=(bij)r×n,則矩陣C=(cij)m×n,其中cij=ai1b1j+ai2b2j+…+airbrj

稱爲A與B的乘積,記作C=AB。

這裏上個代碼:

 1 for(int a=1;a<=m;a++)
 2 {
 3     for(int b=1;b<=r;b++)
 4     {
 5         for(int c=1;c<=n;c++)
 6         {
 7             m3[a][c]+=m1[a][b]*m2[b][c];
 8         }
 9     }
10 } 

舉個栗子:

和菲波那契的關係

[fn-1 fn]×=[fn fn+fn-1]=[fn fn+1]

因此咱們要計算[0 1]的斐波那契數列,只要不斷地×便可=[fn fn+1]。

特別地,矩陣乘法沒有交換律:AB≠BA!

咱們還能夠結合快速冪進行斐波那契的計算,例如:[0 1]×11,能夠進行以下變換:把11的指數11拆成8+2+1,即爲23+21+20,而後運用快速冪把這些乘起來便可。

一個小小的問題:這個是怎麼推出來的呢?

咱們假設有方程f(n)=af(n-1)+bf(n-2),因此斐波那契就是當a=b=1時的特殊狀況,根據矩陣乘法,咱們假設這個矩陣爲[ ],而且這個矩陣確定是2×2的,因此有:[fn fn-1=[fn+1 fn]。因此有fn+1=wfn+yfn-1fn=xfn+zfn-1,因此:fn+1=afn+bfn-1fn+1=wfn+yfn-1,→a=w,b=y。

觀察方程左右,令x和z等於1和0,便可得出這個[ ]爲=

一個補充的知識點

則方程組可寫爲Ax=b。

矩陣乘法的一些性質

0A=0,A0=0

IA=A,AI=A

A(BC)=(AB)C

A(B+C)=AB+AC

(B+C)A=BA+CA

7.逆矩陣

定義:設A是n階方程,若是存在n階方陣B使得AB=BA=I,則稱A是可逆的(或者非奇異的),B是A的一個逆矩陣,不然稱A是不可逆的(或奇異的)。

定理:逆矩陣若是存在,則逆矩陣惟一。

定義:det運算符:

定理:設A、B是n階方程,則:det(AB)=det(A)det(B)

證實的提示:構造

引理:det(A1A2…As)=det(A1)(A2)(As)。

引理:設A爲n階方陣,AX=0有非零解的充分必要條件是A奇異。

引理設A爲n階方陣,若∃B爲n階方陣,使得AB=I(或BA=I),則A可逆且A-1=B。

引理:若det(A)≠0,則det(A-1)=(det(A))-1

求解逆矩陣的方法

①待定係數法

②公式法:A-1=(1/(det(A)))A*

③定義法:若AB=I,則B=A-1

逆矩陣的性質

(A-1)-1=A

(AB)-1=B-1A-1

(kA)-1=k-1A-1

定理:設A爲n階方陣,若A可逆,則線性方程組AX=b有惟一解X=A-1b

8.初等變換

定義:矩陣的初等行/列變換

<1>用一個非零的數乘以某行

<2>將某一行的k倍加到另外一行

<3>互換兩行

定義:單位陣I通過一次初等變換獲得的矩陣稱爲初等矩陣。

初等矩陣:

定理:用初等矩陣左(右)乘矩陣A,至關於對矩陣A實行相應的初等行(列)變換

定理初等矩陣均可逆。

定義:若矩陣B能夠由矩陣A通過一系列初等變換獲得,則稱A與B相抵(等價),記作A≌B。

定理相抵是一種等價關係。

初等變換求逆矩陣:構造一個n×2n的矩陣(AI)

A-1(AI)=(A-1AA-1)=(IA-1)

(AI)→…→(IA-1)一系列的初等變換

最近發現一些網站盜用個人blog,這實在不能忍(™把關於個人名字什麼的所有刪去只保留文本啥意思。。)!!但願各位轉載引用時請註明出處,謝謝配合噢~

原博客惟一地址:http://www.cnblogs.com/geek-007/p/7296446.html

相關文章
相關標籤/搜索