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...