ACM學習羣裏接觸到的問題,既然假期有時間就寫個總結吧。php
部份內容參考了:html
http://www.2cto.com/kf/201207/144626.htmlapp
http://www.doc88.com/p-272339677599.html學習
題意:n條直線,最多能夠把平面分爲多少個區域。
思路:當有n-1條直線時,平面最多被分紅了f(n-1)個區域。則第n條直線要切成的區域數最多,就必須將直線儘量兩兩相交,而避免多條直線相交於一點和平行關係的出現。這樣就會獲得n-1個交點。這些交點將第n條直線分爲2條射線和n-2條線段。而每條射線和線段將以有的區域一分爲二。這樣就多出了2+(n-2)個區域。
由此可得:f(n) = f(n-1)+n = f(n-2)+(n-1)+n =f(1)+1+2+……+n = n(n+1)/2+1。spa
根據直線分平面可知,由交點決定了射線和線段的條數,進而決定了新增的區域數。當n-1條折線時,區域數爲f(n-1)。爲了使增長的區域最多,則折線的兩邊的線段要和n-1條折線的邊,即2*(n-1)條線段相交。那麼新增的線段數爲4*(n-1),射線數爲2。但要注意的是,折線自己相鄰的兩線段只能增長一個區域。
由此可得:f(n) = f(n-1)+4(n-1)+2-1 = f(n-1)+4(n-1)+1 = f(n-2)+4(n-2)+4(n-1)+2 = f(1)+4+4*2+……+4(n-1)+(n-1) = 2n^2-n+13d
#include <cstdio> int main () { int T,n; scanf("%d",&T); while (T--) { scanf("%d",&n); printf("%d\n",2*n*n-n+1); } return 0; }
該問題只討論兩兩橢圓只有兩個交點的狀況code
題意:有n條封閉曲線畫在平面上,而任何兩條封閉曲線剛好相交於兩點,且任何三條封閉曲線不相交於同一點,問這些封閉曲線把平面分割成的區域個數。htm
設橢圓數爲n,分割數爲S(n)blog
則:S(1)=2 , S(2) =4 , S(3)=8 , S(4)=14 ……get
思路:當n-1個圓時,區域數爲f(n-1).那麼第n個圓就必須與前n-1個圓相交,則第n個圓被分爲2(n-1)段線段,增長了2(n-1)個區域。
則: f(n) = f(n-1)+2(n-1) = f(1)+2+4+……+2(n-1) = n^2-n+2
設三角形數爲n,分割數爲S(n)
則S(1)=2 , S(2)=8 , S(3)=20 , S(4)=38
當 n=2 時,新增的三角形與原有的三角形有了6個交點,即每邊兩個交點,也就產生6個新增區域,同理遞推
遞推式:S(n) = S(n-1)+6(n-1)
S(n)=3*n^2-3*n+2
#include <cstdio> int main () { int T,n; scanf("%d",&T); while (T--) { scanf("%d",&n); printf("%d\n",3*n*n-3*n+2); } return 0; }
由二維的分割問題可知,平面分割與線之間的交點有關,即交點決定射線和線段的條數,從而決定新增的區域數。試想在三維中則是否與平面的交線有關呢?當有n-1個平面時,分割的空間數爲f(n-1)。要有最多的空間數,則第n個平面需與前n-1個平面相交,且不能有共同的交線。即最多有n-1 條交線。而這n-1條交線把第n個平面最多分割成 g(n-1)個區域。(g(n)爲問題一中的直線分平面的個數)此平面將原有的空間一分爲二,則最多增長 g(n-1) 個空間。
則:f=f(n-1)+g(n-1) ps:g(n)=n(n+1)/2+1
=f(n-2)+g(n-2)+g(n-1) = f(1)+g(1)+g(2)+……+g(n-1) = 2+(1*2+2*3+3*4+……+(n-1)n)/2+(n-1)=(1+2^2+3^2+4^2+……+n^2-1-2-3-……-n )/2+n+1=(n^3+5n)/6+1
#include <cstdio> int main () { int n; while (~scanf("%d",&n)) printf("%d\n",(n*n*n+5*n)/6+1); return 0; }
補充:Acdream 1080
題目連接:http://acdreamoj.sinaapp.com/problem.php?id=1080
#include <cstdio> long long Deal (long long s,long long e,long long n) { if (e-s<=4) { for (long long i=s;i<=e;i++) if (i*i-i+2>=n) return i; } long long mid = (s+e)>>1; if ( mid*mid-mid+2 >= n ) return Deal (s,mid,n); else return Deal (mid+1,e,n); } int main () { int n,T; scanf("%d",&T); while (T--) { scanf("%d",&n); if (n==0 || n==2) printf("1\n"); else printf("%lld\n",Deal (0,200000,n)); } return 0; }