# 2022q2 Homework (quiz5)
contributed by <`ray90514`>
## 測驗一
依照程式碼,主循環如下
1. 判斷該迴文數長度是否為偶數,如果是該數必不為質數,找出下一個長度為奇數的迴文數
2. 判斷是否為 3 或 5 的倍數,判斷是否為質數
3. 求出下一個迴文數
判斷 3 和 5 的倍數有比較直接的方法,判斷質數則要先產生一個質數表,然後看質數表中的質數能否被該數整除。質數表的產生使用 Sieve of Eratosthenes 搭配 bitset 產生出小於等於 $sqrt(n) 的質數$。因為偶數除了 2 一定不是質數,只要記錄奇數就好。 以 bitset 儲存的質數表第 n 位為 0 代表 2n + 1 是質數,使用時先將質數表取反搭配 `__builtin_ctzll` 即可快速找到質數表中的質數。
```c
/* Check if a number is prime. */
static bool isprime(const ull val)
{
if (!(val & 0x1)) /* Test for divisibility by 2 */
return false;
ull *pquadbits = (ull *) psieve;
ull next = 3; /* start at 7 (i.e. 3 * 2 + 1) */
for (ull quad = ~*pquadbits & ~0b111, prev = 0; prev <= half_max;
quad = ~*++pquadbits) {
if (!quad) {
prev += 64;
continue;
}
while (quad) {
ull i = EXP1;
next = prev + i;
if (!(val % ((next << 1) + 1)))
return false;
quad &= EXP2;
}
prev += 64;
}
return true;
}
```
使用上將質數表以 ull 為單位存取,根據前面之敘述以及 `val % ((next << 1) + 1)` 可以得出 next 就是第 n 位的 n ,也就是說 `prev + i` 為當前要找的質數的位數, `prev` 是之前已找的位數,則 `i` 是下一個質數在當前存取的 `quad` 的第幾位,也就是最低位的 1 在第幾位,用 `__builtin_ctzll(quad)` 求得。判斷完該質數後要將 `quad` 中該位清除,所以 `EXP2` 為 `~(1ULL << i)` 。
產生下一個迴文數的方式為,依照前一個迴文數,修改其中某一位數及對稱的位數,從 0 到 9 ,直到每一位都不能被修改則產生 len + 1 位的新迴文數。
### 改進
## 測驗二
###### tags: `linux2022`