退役前最後一篇部落格。。。希望我滾回去高考完還能記得一些oi知識
最近考試我們有一道這樣的題目:
如果有兩個序列a和b,對於a序列中的每乙個元素,都在b序列中選乙個大於等於它的最小的值。若a序列選出的不同的b序列元素個數為奇數則稱之為好的。現在給出n個序列s1..n,對於每兩個序列si,sj(i首先std給出了這樣的題解:看起來十分簡潔但是對我這種noip(普及組初賽)水平選手卻並不容易想到,因此考試的時候我得到了乙個不怎麼優的做法:分塊因為所有的位置範圍是[1,50],我們可以用位運算加速統計。將序列 b 轉換成乙個二進位制數b,將序列 a 轉換成乙個二進位制數 a,我們要統計的是 a 中的某些特定區間內是否有二進位制 1。令b ′ = b ≪ 1,則b ′ &(a + (a|~b ′ ))中的二進位制 1 即表示a的對應區間內是否有 1,統計其二進位制 1 的奇偶性即可。
分析:首先我們可以發現一共有c(n,2)種選法,這個數量大約是1.25e7。那麼對於每個的判斷我們有8次操作的時間完成。
問題顯然可以轉化為二進位制,那麼我們可以得到乙個二進位制下的50位數。
位數不多,情況只有01兩種,所以考慮採用分塊。
令塊的大小為s,那麼在塊內我們總共有4^s種方案,每種方案我們可以在o(s)的時間內處理出它填到了塊內b序列中的哪些位置,以及是否有剩餘的沒填的。順便對於每一種b序列的塊,處理左邊第乙個1在**。
換句話說,預處理的時間複雜度為o(4^s*s)。
對於每兩個序列,預先分好塊,不足的補滿,最大塊數為5塊。從左到右掃瞄每一塊,並查表得到答案,並和上乙個的答案合併,合併的時候要考慮上一塊是否多餘了一些。
可以發現每一次詢問的時間複雜度為o(m/s),共o(n^2)組詢問,總時間o(n^2*m/s)。
總的來說,時間複雜度為o(4^s*s+n^2*m/s)。
分析分塊大小,通過解方程我們知道s=10時比較優,實測可以過,最大資料0.2秒。
奉上**:
1 #include2 using namespacestd;3 4 intn;
5 int num[5010];
6 int a[5010][53];
7 long long res[5010][7];
8 long long pp[1050][1050];
9 long long rm[1050][1050];
10 int frt[1050];
11 12 voidread()
19 for(int j=1;j<=num[i];j++)
22 for(int j=1;j<=5;j++)
27 }
28 }
29 }
30 }
31 32 void deal(int tot,inttt) }
38 }
39 }
40 41 void dfs2(int now,int tot,inttt)
43 else
47 }
48 49 void dfs1(int now,inttot){
50 if(now > 10){
51 for(int i=0;i<=10;i++){if((tot&(1<
更進一步地靈活運用它,我們再來看一道題。
維護乙個序列,支援單點修改,區間和的phi值查詢以及區間乘法的phi值查詢。其中序列長度n為50000,值的大小ai為40000,詢問個數q為100000題解給出了一種基於二分的方法,但是對我這種noip(普及組初賽)水平選手卻並不容易想到,因此考試的時候我得到了乙個不怎麼優的做法:分塊。
對於加法我們比較容易想到乙個n^1.5的列舉質因數的做法。所以我們只考慮修改和乘法。
考慮從phi的定義入手,那麼我們只需要考慮l到r之間哪些素數是出現過的,由於ai在40000以內,所以我們發現質數個數接近40000/ln(40000)個。
使用bitset維護合併,建一棵線段樹維護區間內的bitset的並集。
這樣子,單次修改操作會改變logn個bitset的內容,時間複雜度為o( (logn*ai) / (ln(ai)*w) ),我們可以認為ai和n同階,時間複雜度為o(n/w).
考慮每次區間乘法操作,需要合併logn個bitset,這一部分時間複雜度同上。
另外的,我們需要對合併結果進行處理,也就是對bitset的每個位對應的p都處理一次,這個操作的時間複雜度o(n/ln(n)).
當三種操作平均分布的時候,我們的時間複雜度為o(q*(sqrt(n)+n/w+n/ln(n))).
這個演算法有優化的空間,我們發現n/ln(n)是我們演算法速度的瓶頸。帶入數字可以發現,當操作不隨機的時候,我們可以構造乙個資料,使得總執行次數達到3.7e+8次。其中光是n/ln(n)就佔了3e+8。
實際上,我們有大量的運算是重複的。
下面我舉乙個例子。
考慮01串
我們將它按每4位算一組,當我們計算這兩個01串的時候,我們要計算8次。但如果我們預處理出了每4位對應的答案,那麼我們只要計算6次。
這在q很少的時候優化不明顯,但是當q的級別很大的時候,那麼這樣可以節省很多運算。
對於上面的2操作得到的最終的並,我們可以將它每16位分為一組,通過dp預處理出答案。dp的轉移是o(1)的,所以dp預處理的時間複雜度為o(n*2^16/16)。
接著我們對於最終的並,每16位作為乙個整體在表中直接查詢答案,時間複雜度可以在原來的基礎上除以16,令16=v,2操作的時間複雜度被降低為o(n/w+n/ln/v),同樣的資料只用計算1e+8次。
值得注意的是,這並不是乙個玄學的優化,而是一類有體系的優化方法。
這種方法同樣也被運用在rmq問題中,有興趣的可以學一下
從考試看到自己的能力與不足
今天上午產品線安排了上機考試,好久沒有這種程式設計考試了。題目如下 1 乙個公司,銷售部門,採購部門 每個部門的資料用不同格式的檔案儲存 txt,xml 其他的還有可能db之類的,考試不做要求,但要求將來擴充套件時不修改 2 每個檔案包括n個員工的資訊,包括 部門,姓名,工號,性別,工作地,入職時間...
計算機等級考試一級B考試模擬試題一
1 計算機的特點是處理速度快 計算精度高 儲存容量大 可靠性高 工作全自動以及 a 造價低廉 b 便於大規模生產 c 適用範圍廣 通用性強 d 體積小巧 答案 c 解析 計算機的主要特點就是處理速度快 計算精度高 儲存容量大 可靠性高 工作全自動以及適用範圍廣 通用性強。2 1983年,我國第一台億...
計算機等級考試一級MSOffice模擬題(17)
選擇題 每小題1分,共20分 1 以下不是我國知名的高效能巨型計算機的是 a 銀河 b 曙光 c 神威 d 紫金 2 無符號二進位制整數llll001轉換成十進位制數是 a 117 b 119 c 120 d 121 3 十進位制數57轉換成二進位制整數是 a 0111001 b 0110101 c...