LOJ 143 質數判定 題解

2022-02-14 15:59:11 字數 1889 閱讀 7048

csdn同步

原題鏈結

簡要題意:

給定 \(t\) 個數 \(n\),判素數。

\(t \leq 10^5 , n \leq 10^\).

可能你判乙個都有困難是不是 \(\cdots \cdots\).

若 \(x^2 \equiv 1 \pmod p , x < p\),則 \(x= 1\) 或 \(x = p-1\).

簡單證明:

\[x^2 \equiv 1 \pmod p

\]\[(x-1)(x+1) \equiv 0 \pmod p

\]沒了。

如何快速測試乙個數是否為素數?這是基於二次探測定理的。

大家一定知道偽素數吧!就是那些費馬小定理逆定理的反例,以其中最小的 \(341\) 為例,先以 \(2\) 為底:

\(2^ \equiv 1 \pmod \),第一次通過。

\(2^ \equiv 1 \pmod \),第二次通過。

\(2^ \equiv 32 \pmod \),說明 \(341\) 不是素數。當然如果這一次通過則說明 \(341\) 通過了 \(2\) 的底數檢測,因為 \(85\) 是奇數。

當然同樣的道理,我們可以以其它素數為底進行判斷。這樣的成功效率是多少呢?

假設你判斷了 \(k\) 個素數,那麼錯誤的概率是 \(4^\),實際上和 \(0\) 也差不多。

只用 \(2,7,61\) 進行測試盡可以保證 \(4 759 123 141\) 之內正確。

如果你用 \(2,3,5,7,11,13,17\) 進行測試,可以保證 \(341 550 071 728 320\) 之內所有數正確。

如果選用 \(2, 3, 7, 61,24251\) 作為底數,\(10^\) 之內就存在乙個反例:\(46856248255981\).(當然是 \(10^\) 之內唯一的反例,說明了正確的概率之高)

這題是 \(10^\),本人採用 \(2,3,5,7,11,61,24251\) 可以通過。(當然你也可以用合數進行測試,但合數效率不高)另外本人還新增了 \(10\) 組隨機測試(即隨機生成底數進行測試),保證了正確性。

時間複雜度:\(\mathcal(t \log^2 n)\). 錯誤概率:\(4^\).

實際得分:\(100pts\).

細節:快速冪中的相乘會溢位,本人的編譯器不知道怎麼typedef __int128 ll會編譯錯誤,所以用了long double進行乘法的轉移。(不是龜速乘啊)

#pragma gcc optimize(2)

#includeusing namespace std;

typedef long long ll;

inline ll read()

ll x=0; while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x*f;}

inline void write(int x)

if(x<10)

write(x/10);putchar(char(x%10+'0'));

}ll prime[8]=;

inline ll times(ll x,ll y,ll mod) //計算 x*y

inline ll pw(ll x,ll y,ll mod) return ans;

} //快速冪

inline bool check(ll x,ll y,ll mod)

inline bool miller_rabin(ll n) for(int i=1;i<=10;i++) return 1;

}int main()

LOJ 143 質數判定

給定乙個數 n 判斷是否是質數。n leq 10 miller rabin 素數測試板子題。推薦部落格。質數有兩個性質。一是眾所周知的費馬小定理 若 p 是質數,且 x 不是 p 的倍數,則 x equiv 1 pmod p 還有乙個二次探測定理。如果 p 是質數且 x 2 equiv 1 pmod...