NOIP2007 提高組 題解

2022-09-11 20:18:12 字數 3019 閱讀 2302

2007 提高組題解

第一題 一開始還想是不是要用雜湊表儲存呢,但仔細想了一會兒,那個資料量20w 用個快排序,時間是能過的。所以這道題用個stl的快排,再乙個迴圈統計個數就ok了。但最後交上去評測時0分,很尷尬。就是我在資料初始化時從一開始計數,我迴圈又從一開始,***,多算了一次,爆掉了。改了就100了。200w的話資料就很強了,用雜湊好一些。

第二題 額,寫得很快,果然這種無腦模擬題最適合我了。但自信沒檢查,帶了3組給的資料就走了。果然錯了,過了4個點好像。主要是題沒讀完,沒有判斷處於字母和數字的情況,然後輸出了一堆亂七八糟的字元,嗯,爆了。完了之後9分,哇,好氣啊。再核對了一遍資料,額,我處理轉大寫時是這樣寫的:/* buffer – 『a』+ 『a』*/ 帶數字進去可想而知是什麼鬼了,我開始看資料時是『3』變為了 ! 我還以為是十進位制變成了十六進製制呢。= =

第三題 處理了前60% 的資料,但答案沒有高精,40分。聽了orange lee 的類的高精度處理講解後,有了那麼點感覺,但還是很不熟悉,這種果然還是要平時多寫,其實主要是不怎麼喜歡高精,感覺陣列處理起來很煩,能用long long 的題就是好題。總的來說是一道區間dp,主要難點還是高精的處理上。

第四題 做了半天也就不想做了,加上讀了半天題沒讀懂很心累。其實是floyd演算法求直徑,然後根據情況來選取偏心距。

首先來考慮只有一條直徑的時候,後面會說明有多條直徑的時候可以當作一條來處理。首先可以通過經典的o(n)的演算法求出樹上的最遠點,即一條直徑(做法是從任意一點開始dfs一次求出乙個最遠的點,這是直徑的乙個端點;再從這個最遠點開始再次dfs,再找到的最遠點就是直徑的另外乙個端點)。然後順序列舉這條最長路徑上的每條長度小於s的最長子路徑(說不太清楚看**吧...),用乙個佇列維護。這樣每一條可能的路徑就是乙個可能的核,再求出對應的偏心距就可以了。我是先用了乙個floyd預處理出所有頂點之間的最點路備用。 ok,來說有多條直徑的問題: 題目中已經說了,如果有多條直徑的話他們的中心也一定重合,換言之一定至少有乙個節點或一條路徑重合。假設有兩條直徑分別為ab和cd,它們重合的部分是ef。那麼一定有ae的長度等於ce的長度,fb的長度等於fd的長度。其次核一定是在直徑的**部分。下面分兩種情況討論: 1. 如果給定的s能夠覆蓋重合的點或者路徑,那麼我們在任一條直徑上選擇乙個核,那麼對於另外的直徑而言,就是只選擇了重合的部分,對於這個核的偏心距「有貢獻」的只可能是在非選中的直徑上,而對於每條直徑除去重合部分剩下的兩部分的長度都是相等的,所以選擇任意一條直徑均可。 2. 如果不能覆蓋,那麼對於所有直徑選擇的部分都是相同的了,更是可以任選了。 兩點還可以改進的地方,由於資料不是很強,我也就沒改: 1. 核一定是在直徑的**部分,所以可以從直徑的中心向兩邊擴充套件求核。 2. 距離核最遠的點一定是度為1的點,floyd預處理有點浪費了。

#include#include

using

namespace

std;

int data[200010

];int

n,comp,tot;

intmain()

}printf(

"%d %d\n

",comp,tot);

return0;

}

#include#include

using

namespace

std;

intp1,p2,p3;

char str[110

];int

main()}}

else}}

}else

}return0;

}

#include#include

#include

using

namespace

std;

const

int power=4

;const

intbase=10000

;const

int maxl=10

;struct

num num

operator + (const num &b)

if (c.a[c.a[0]+1])++c.a[0

];

return

c; }

num

operator + (const

int &b)

if (a[a[0] + 1]) a[0]++;

return *this

; }

num

operator = (int

b)

return *this

; }

bool

operator

< (const num &b) const

return

false

; }

void

print()

} ans,f[maxn][maxn];

intmain()

}ans = ans + f[1

][m];

ans = ans + f[1

][m];

}ans.print();

return0;

}

#include#include

using

namespace

std;

int map[350][350],deal[350

];int n,lev,x,y,value,ans = 2147483647

;int

main()

for(int k=1; k<=n; k++)}}

int record = 0

;

for(int i=1; i<=n; i++)}}

for(int i=1; i<=n; i++)

if(map[x][i] + map[i][y] == map[x][y]) deal[++deal[0]] =i;

for(int i=1; i<=deal[0]; i++)

}cout

}

NOIP2007提高組題解

考察知識 快速排序,map的基本操作 演算法難度 xx x 實現難度 xx x 分析 如果用快排的話,要用分治思想,難度稍微大一些,用map就是基本操作,難度不大 如果追求速度可以寫乙個快速輸入函式,但是注意輸入是否有負數 map版 含快速輸入 include include includeusin...

noip2007提高組題解

第一題 統計數字 排序 平衡二叉樹 受上面這篇文章的影響,我沒有用快排,而是用了stl的multiset的count函式來統計出現次數。但事實證明stl的sort足以應付此題。另外的解法是用treap實現的名次樹,效率不及sort但高於multiset。第二題 字串的展開 模擬 雖然是模擬題但是可惜...

NOIP2007提高組 樹網的核

noip2007提高組試題4。設 t v,e,w 是乙個無圈且連通的無向圖 也稱無根樹 每條邊帶有正整數的權,我們稱 t 為樹網 treenetwork 其中 v,e 分別表示結點與邊的集合,w 表示各邊長度的集合,並設 t 有 n 個結點。路徑 樹網中任何兩個結點 a,b 都存在唯一的一條簡單路徑...