programming:acm_temp
差異處
這裏顯示兩個版本的差異處。
| 兩邊的前次修訂版前次修改 下次修改 | 前次修改 | ||
| programming:acm_temp [2007/04/11 19:08] – 10127 wenpei | programming:acm_temp [2014/02/11 17:17] (目前版本) – sars | ||
|---|---|---|---|
| 行 1: | 行 1: | ||
| - | Hash、 | + | * [[http:// |
| + | |||
| + | |||
| + | Hash、大數、質因數分解、質數 | ||
| + | |||
| + | |||
| + | ====== 146 ====== | ||
| + | 給一個字串,找出下一個權重的字串。可用 algorithm.h 中的 bool next_permutation(iterator_start, | ||
| + | abaacb -> ababac | ||
| + | cbbaa -> no solution(lastest one) | ||
| + | 另解:從最右邊開始往左找,直到找不到遞增關係停止,前面一樣,然後找下一個即可。如 abaacb 中,最右邊 cb 為遞增,但到 acb 即非遞增,因此可找 acb 的下一個 bac,然後前面一樣。 | ||
| ====== 642 ====== | ====== 642 ====== | ||
| 行 17: | 行 27: | ||
| 利用長除法的原理,將每次的餘數乘以十加上一,然後再用 n 除一次,再取餘數,直到整除,算加了幾次 1 即可。 | 利用長除法的原理,將每次的餘數乘以十加上一,然後再用 n 除一次,再取餘數,直到整除,算加了幾次 1 即可。 | ||
| + | |||
| + | 或: | ||
| + | < | ||
| + | 10 ≡ 3 (mod 7) | ||
| + | 100 ≡ 30 ≡ 2 | ||
| + | 1000 ≡ 20 ≡ 6 | ||
| + | 10000 ≡ 60 ≡ 4 | ||
| + | 10^5 ≡ 40 ≡ 5 | ||
| + | |||
| + | 1 + 3 + 2 + 6 + 4 + 5 = 0 (mod 7) | ||
| + | </ | ||
| + | |||
| + | ====== 10225 ====== | ||
| + | http:// | ||
| + | |||
| + | B^L ≡ N (mod P) | ||
| + | |||
| + | Shank' | ||
| + | m = ceiling( √(P-1) ) | ||
| + | 0 <= i <= m-1 | ||
| + | 0 <= j <= m-1 | ||
| + | ...... | ||
| ====== 10745 ====== | ====== 10745 ====== | ||
| 行 22: | 行 54: | ||
| 字串長度最大 10,依照字典排序印出不會被其他字串所包含(dominant)的字串,若 A 字串單字長度大於 B 字串,代表 B 絕對不可能 dominant A,同 642 方法試試。 | 字串長度最大 10,依照字典排序印出不會被其他字串所包含(dominant)的字串,若 A 字串單字長度大於 B 字串,代表 B 絕對不可能 dominant A,同 642 方法試試。 | ||
| + | |||
| + | ====== 陣列跟指標 ====== | ||
| + | http:// | ||
| + | |||
| + | < | ||
| + | 當我們宣告一個陣列時, | ||
| + | 那它指向哪裡呢? | ||
| + | 以下面的code為例: | ||
| + | |||
| + | int a[5]; | ||
| + | |||
| + | 這宣告了一個陣列, | ||
| + | 我假設它在記憶體裡長這樣: | ||
| + | |||
| + | ─┬──┬──┬──┬──┬──┬─ | ||
| + | | ||
| + | ─┴──┴──┴──┴──┴──┴─ | ||
| + | |||
| + | 我們知道可以用 | ||
| + | 是陣列天生的性質 -- 連續的記憶體位置, | ||
| + | 透過 index 算出來..(超秘: | ||
| + | |||
| + | 而前面提到的, | ||
| + | 等式是成立的: | ||
| + | |||
| + | a == &a[0] == &(0[a]) | ||
| + | *a == a[0] == 0[a] | ||
| + | |||
| + | 我們都知道 & 當作一元運算子(unary operator, 也就是只有 | ||
| + | 一個運算元的運算子)時, | ||
| + | 所以 &a[0] 自然是解釋作 取第一個元素的位址, | ||
| + | 的值了。而 * 作一元運算子時, | ||
| + | 意思, 所以 *a 就是取第一個元素的值, | ||
| + | |||
| + | 既然 name[index] 幫我們作了記憶體計算的工作, | ||
| + | 也可以用指標來做類似的動作, | ||
| + | 的值, 要怎麼算出 a[1] 的位址呢? | ||
| + | |||
| + | a + 1 | ||
| + | |||
| + | 咦? 不是說 int 佔 4 bytes嗎?, 為什麼 +1 就好了而不是 +4 ? | ||
| + | 因為 compiler 看得出來左邊的運算元是一個 int *, 所以它在 | ||
| + | 做加法時, | ||
| + | a 和 a+1 的值, 你輸出後其實是相差4的 (可以自己實驗..) | ||
| + | 所以導出下列等式: | ||
| + | |||
| + | a + i == &a[i] == &i[a]; | ||
| + | *(a+i) == a[i] == i[a]; | ||
| + | |||
| + | 所以我們在函式間傳遞陣列時, | ||
| + | 就是這個道理 (多維陣列下面會講) | ||
| + | |||
| + | |||
| + | 至於多維陣列呢? | ||
| + | |||
| + | int b[3][2]; | ||
| + | |||
| + | 這樣我們該怎麼解讀呢? | ||
| + | 讀一樣: | ||
| + | |||
| + | ← | ||
| + | ┬────┬────┬────┬────┬────┬────┬─ | ||
| + | ... │ b[0][0]│ b[0][1]│ b[1][0]│ b[1][1]│ b[2][0]│ b[2][1]│... | ||
| + | ┴────┴────┴────┴────┴────┴────┴─ | ||
| + | |||
| + | 而其記憶體計算的方式跟上述一維陣列的例子相仿: | ||
| + | |||
| + | b == b[0] == & | ||
| + | *(*(b+1)) == b[1][0] == *(b[0] + 2) | ||
| + | |||
| + | // 你可以看得懂上面這行就表示你懂了 | ||
| + | |||
| + | 因為這樣, | ||
| + | 都必須宣告清楚, | ||
| + | 的結果 (以此例而言, | ||
| + | b[0] + 1 是要加 8啊) | ||
| + | |||
| + | 所以本來我們都會這樣做: | ||
| + | |||
| + | void foo(int array[][2]) | ||
| + | { | ||
| + | .... | ||
| + | } | ||
| + | |||
| + | |||
| + | int b[3][2]; | ||
| + | foo(b); | ||
| + | |||
| + | 但是學會指標後我們可以這麼做: | ||
| + | |||
| + | void foo(int** array, int size1, size2) | ||
| + | { | ||
| + | ..... | ||
| + | } | ||
| + | |||
| + | |||
| + | int b[3][2]; | ||
| + | foo( (int **)b); | ||
| + | |||
| + | 不過這樣的話, | ||
| + | 再更高維的就以此類推吧... | ||
| + | |||
| + | [ Pointer array / Pointer to array] | ||
| + | |||
| + | 這裡開始進入火星文區 | ||
| + | |||
| + | 以下兩個例子: | ||
| + | |||
| + | int* a[3]; | ||
| + | int (*b)[3]; | ||
| + | |||
| + | 你知道它們差別在哪裡嗎? | ||
| + | int* a[3]; 是一個陣列名為 a, 有三個元素, | ||
| + | int (*b)[3]; 則是一個指標名為 b, 它指向一個 int[3] 的陣列 | ||
| + | |||
| + | 用圖形來看就是: | ||
| + | int data[3]; | ||
| + | int* a[3]; int (*b)[3]; | ||
| + | |||
| + | a → ├─┤ | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | |||
| + | |||
| + | 我想看圖之後就會非常了解了吧 :) | ||
| + | 如果這個圖沒有問題的話, | ||
| + | </ | ||
| + | |||
| + | ====== 指標的資料型態 ====== | ||
| + | http:// | ||
| + | |||
| + | < | ||
| + | 當我們在宣告一個指標(pointer)時, | ||
| + | 它存著某個記憶體位址, | ||
| + | 其它的記憶體上的運算。那這個變數在記憶體中佔幾個 byte 呢? | ||
| + | 這個答案跟 int 一樣: machine-dependent, | ||
| + | 及 compiler 而言, 指標變數也是佔32bits == 4 bytes的大小, | ||
| + | 而它內容, | ||
| + | 指標都是 4bytes 的變數: | ||
| + | |||
| + | char* a; short* b; int* c; double* d; | ||
| + | |||
| + | 它們的差異, | ||
| + | 取出 n bytes 來取值。比方說 *d 就是從 d 開始抓 8bytes 出來 | ||
| + | 並且照 IEEE 754 的表示法來得到這個浮點數的值。 | ||
| + | |||
| + | 陣列的話, | ||
| + | 就算以後教到 struct 也是同樣的道理。 | ||
| + | |||
| + | |||
| + | [函數指標] | ||
| + | |||
| + | 既然, 基本型態的變數, | ||
| + | 函式會沒有呢? | ||
| + | 指標指到它的位址呀, | ||
| + | 了, 你呼叫函數的時候, | ||
| + | 一般, 函數的名稱就是它的pointer, | ||
| + | |||
| + | char foo(short a, int b, float c, double d, int f[]); | ||
| + | |||
| + | 那麼 foo 就是這個函數的指標, | ||
| + | |||
| + | char (short, int, float, double, int []) | ||
| + | |||
| + | 這個資料型態, | ||
| + | |||
| + | int **a; | ||
| + | int data[3]; | ||
| + | int (*b)[3]; | ||
| + | |||
| + | b = & | ||
| + | a = &((int *) data); | ||
| + | |||
| + | b 就是一個指到 int [3] 的指標呀, | ||
| + | 上面啦。而如果我們要宣告一個這樣資料型態的指標, | ||
| + | |||
| + | char (*p2f)(short, | ||
| + | |||
| + | p2f = foo; /* 注意: 跟陣列的例子有出入 */ | ||
| + | /* p2f = &foo 也可以, 你可以想想為什麼 */ | ||
| + | |||
| + | |||
| + | 這樣一來我們就可以用 p2f 指到 foo 這個函式了, | ||
| + | |||
| + | char ch; | ||
| + | ch = p2f(a, b, c, d, e, f); | ||
| + | /* 同上 ch = (*p2f)(a, b, c, d, e, f); 也一樣*/ | ||
| + | |||
| + | 就好像真的去使用 foo 一樣, 雖然我們是用 p2f。 | ||
| + | |||
| + | 所以呢, 利用這樣的觀念, | ||
| + | -- functions 的宣告及設定。(再說下去就要變答案了....orz) | ||
| + | |||
| + | |||
| + | [typedef] | ||
| + | |||
| + | typedef 關鍵字是用來替資料型態取個「別名」(alias), | ||
| + | 你叫出 「上官林傑」、「ericsk」、「無敵親切超級帥氣助教」 | ||
| + | 都可以指到我, | ||
| + | |||
| + | 比方說我們可以 | ||
| + | |||
| + | typedef long long INT64; | ||
| + | typedef int INT32; | ||
| + | |||
| + | 這樣表示幫 int 型態取了個別名 INT32, 之後我們就可以用它來 | ||
| + | 宣告變數。(也幫 long long 取了個別名叫 INT64) | ||
| + | |||
| + | 為什麼要介紹這個呢?這樣便可以幫我們簡化一些東西, | ||
| + | 的例子: | ||
| + | 可是我們卻不能用 int[3] *b; 來宣告 b, 這樣實在不是很直覺, | ||
| + | 但若是用了typedef | ||
| + | |||
| + | typedef int (*P2I3)[3]; | ||
| + | P2I3 b; | ||
| + | b = &data; | ||
| + | |||
| + | 如此一來, | ||
| + | 資料型態, | ||
| + | |||
| + | typedef char (*PF)(short, | ||
| + | PF p2f; | ||
| + | |||
| + | p2f = foo; | ||
| + | |||
| + | 所以用這樣的表示法, | ||
| + | |||
| + | |||
| + | [後記] | ||
| + | |||
| + | 其實打這兩篇, | ||
| + | 除了能讓大家輕鬆解決使徒五之外, | ||
| + | 希望大家都能快樂學習 迅速成長 :D | ||
| + | by 不色助教 | ||
| + | </ | ||
programming/acm_temp.1176289694.txt.gz · 上一次變更: (外部編輯)
