這是一個很大的專題同時也很重要,因此我十分再十分仔細地寫這個筆記,因此有點慢你們別介意。廢話很少說進入正題!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|a2 能夠推出 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+a1;x=k2p2+a2;……
兩個方程爲一組,解之:
k1p1+a1=k2p2+a2移項得:k1p1-k2p2=a2-a1;
在咱們小學的時候,就接觸了一個這樣的解法,很簡單很實用,如今就來模擬一下!
大數翻倍法(一種求解最小公倍數的方法):
舉個栗子:
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-1,fn=xfn+zfn-1,因此:fn+1=afn+bfn-1,fn+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,這實在不能忍(™把關於個人名字什麼的所有刪去只保留文本啥意思。。)!!但願各位轉載引用時請註明出處,謝謝配合噢~