日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数论——判断素数

發布時間:2023/12/9 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数论——判断素数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

數論——判斷素數

小編的話:終于到了數論了

目錄:

文章目錄

  • 數論——判斷素數
    • 1.素數的定義
    • 2. 判斷素數
      • 2.1 判斷素數方法1
      • 2.2 判斷素數方法2
    • 3. 總結

1.素數的定義

  • 在數學里,素數指的是大于1的正整數中,所有只有1和n兩個因子的數,被稱作素數,也叫作 質數
  • 合數:大于1的正整數里,不是質數就是合數
  • 三質數:一個平方數開根之后是質數的平方數叫做三質數

2. 判斷素數

2.1 判斷素數方法1

我們可以想到利用素數的性質來判定素數

洛谷判斷素數, U82118題

#include <bits/stdc++.h> #define int long long using namespace std;bool isprime(int n) {if(n<2) return false;int cnt=0;for(int i = 1; i <= n; i ++){if(n%i == 0) cnt++; // 求出因子的個數}if(cnt==2) return true; // 質數必定是有且僅有兩個因子的數else return false; }main() // 切記不能寫`int main()`! {int x;while(scanf("%lld", &x)==1){if(isprime(x)) puts("Y");else puts("N");}return 0; }

這個大家都能明白吧

時間復雜度O(N2)~O(N^2)~?O(N2)?

這份代碼害的我信用值成了40了

2.2 判斷素數方法2

完全平方數剛剛說過

所有的合數都可以寫成x=y?zx=y*zx=y?z

a?a=ba*a=ba?a=b,那么a2=ba^2=ba2=b

b是完全 平方數

根據反比例函數,可以知道對于所有的合數x,min?(y,z)\min(y, z)min(y,z)都一定小于等于b\sqrt bb?,所以只用枚舉到b\sqrt{b}b?就可以求出答案了。

小計倆:浮點類型不穩定,使用4\sqrt 44?可能等于1.9999991.9999991.999999,然后枚舉到1了。所以浮點數可以加上 一個eps。(eps的取值范圍要注意!一般取值為0.001)

#define int long long #include <cmath>const double eps = 0.001;bool isprime(int x) {if(x<2) return false;double end = 0.001 + sqrt(1. * x);for(int i = 2; (double)i <= end; i ++){if(x % i == 0) return false;}return true; }

sqrt函數 我自己手寫一個看看

double sqrt(double x) // 二分 {if(x<0) return -1;double l = 0, r=1E9;int step=100;double best = -1.0;while(step--){double mid=(l+r)/2;if(mid * mid >= x) {best = mid;r = mid;}else{l = mid;}}return best; }

大家注意一下,sqrt使用的是二分手段,所以時間復雜度≈O(log?N)~\approx O(\log N)~?O(logN)?。乘法只用O(1)O(1)O(1)就能解決。所以 乘法優化:

#define int long long #include <cmath>const double eps = 0.001;bool isprime(int x) {if(x<2) return false;for(int i = 2; i * i <= x; i ++){if(x % i == 0) return false;}return true; }

時間復雜度:O(N?T)O(\sqrt N * T)O(N??T),T是數據的組數

還是太慢,過不了

怎么辦呢?

這個時候就需要使用miller_rabin算法求解了

miller_rabin算法依賴的是費馬小定理

an≡aa^n\equiv aana

當然只有n是質數的時候才可以

但是,費馬小定理是有問題的,是一個假命題,QAQ(遺憾)😢

統計表明,在前10億個自然數中共有50847534個素數,而滿足2n-1 ≡ 1 (mod n)的合數n有5597個

如果用費馬小定理的逆命題來判斷一個正整數n是不是素數,在前10億個自然數中出錯的可能性為0.011%

這個出錯的可能性還是很高的,但是仍然可以用這個技巧來排除大量的合數,這種方法就是費馬檢測

我們可以檢測前面的8~12個質數,如果有一個不滿足,就返回false,全部滿足返回true

這樣出錯概率 就只有(111000)g(\frac{11}{1000})^g(100011?)g了。(g是檢測質數的個數)

在 long long 范圍內,經試驗,不會出錯

但是 有可能越界

使用__int128(洛谷的破綻,noip不允許使用)就能通過

快速乘會超時

#include <iostream> #include <cstdio> #include <cstdlib> using namespace std;typedef __int128 il;int list[8] = {2, 3, 5, 7, 19, 37, 53, 89};il ksc(long long x, long long y, long long z) {il xx = 1;il answer = xx * x * y % z;return answer; // if(y == 0) return 0; // il w = ksc(x, y/ 2, z); // w= (w + w) % z; // if(y & 1) // { // w = (w + x) % z; // } // return w; }long long ksm(long long x, long long y, long long z) {if(y == 0) return 1;il w = ksm(x, y /2 , z);w= ksc(w, w, z);if(y & 1){w = ksc(w, x, z);}return w; }bool miller_rabin(long long n,long long a) {long long d = n -1, r = 0;while((d & 1) == 0){d >>= 1;r ++;}il x = ksm(a, d, n);if(x== 1) {return true;}for(int i = 0; i <r ; i ++){if(x == n - 1){return true;}x =ksc(x, x, n);}return false; }bool isprime(long long n ) {if(n < 2) return false;for(int a= 0;a< 8; a ++){if(n == list[a]){return true;}if(n % list[a] == 0){return false;}if(! miller_rabin(n, list[a])){return false;}}return true; }int main() {long long x;while(scanf("%lld", &x) == 1){if(isprime(x)){puts("Y");}else{puts("N");}}return 0; }

3. 總結

總結

以上是生活随笔為你收集整理的数论——判断素数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。