遇到了一個題:
Description:
Goldbach's conjecture is one of the oldest and best-known unsolved problems in number theory and all of mathematics. It states:
Every even integer greater than 2 can be expressed as the sum of two primes.
The actual verification of the Goldbach conjecture shows that even numbers below at least 1e14 can be expressed as a sum of two prime numbers.
Many times, there are more than one way to represent even numbers as two prime numbers.
For example, 18=5+13=7+11, 64=3+61=5+59=11+53=17+47=23+41, etc.
Now this problem is asking you to divide a postive even integer n (2<n<2^63) into two prime numbers.
Although a certain scope of the problem has not been strictly proved the correctness of Goldbach's conjecture, we still hope that you can solve it.
If you find that an even number of Goldbach conjectures are not true, then this question will be wrong, but we would like to congratulate you on solving this math problem that has plagued humanity for hundreds of years.
Input:
The first line of input is a T means the number of the cases.
Next T lines, each line is a postive even integer n (2<n<2^63).
Output:
The output is also T lines, each line is two number we asked for.
T is about 100.
本題答案不唯一,符合要求的答案均正確
樣例輸入
1
8
樣例輸出
3 5
題解:預處理1e6范圍的素數,暴力這些素數ai 利用素數判定n-ai是否是素數
預處理:線性篩法的模板

#include <bits/stdc++.h> using namespace std; const int maxn=1e6+7; bool check[maxn]; int prime[maxn]; int main(){ int i,j,pos=0,flag; for(i=2;i<maxn;i++){ if(!check[i]) prime[pos++]=i; for(j=0;j<pos&&i*prime[j]<maxn;j++){ check[i*prime[j]]=true; if(i%prime[j]==0) break; } }
然后就是素數的判斷
以下摘錄博客:
https://blog.csdn.net/zengaming/article/details/51867240
https://www.cnblogs.com/SinGuLaRiTy2001/p/6591414.html
先說幾個理論基礎:
1. 費馬小定理:假如p是質數,a是整數,且a、p互質,那么a的(p-1)次方除以p的余數恆等於1,即:a^(p-1)≡1(mod p).
但是反過來卻不一定成立,就是說,如果a、p互質,且a^(p-1)≡1(mod p),不能推出p是質數,比如Carmichael數。
2. 二次探測定理:如果p是一個素數,0<x<p,則方程x^2≡1(mod p)的解為x=1或x=p-1。
3. 模運算的規則:(a*b)%n=(a%n * b%n)%n
4. 快速積取模、快速冪取模:可以看看我之前寫的一篇博客簡單快速的算法
這些理論基礎還沒有好好想過。。
然后是算法的過程:
對於要判斷的數n
1.先判斷是不是2,是的話就返回true。
2.判斷是不是小於2的,或合數,是的話就返回false。
3.令n-1=u*2^t,求出u,t,其中u是奇數。
4.隨機取一個a,且1<a<n
/*根據費馬小定理,如果a^(n-1)≡1(mod p)那么n就極有可能是素數,如果等式不成立,那肯定不是素數了
因為n-1=u*2^t,所以a^(n-1)=a^(u*2^t)=(a^u)^(2^t)。*/
5.所以我們令x=(a^u)%n
6.然后是t次循環,每次循環都讓y=(x*x)%n,x=y,這樣t次循環之后x=a^(u*2^t)=a^(n-1)了
7.因為循環的時候y=(x*x)%n,且x肯定是小於n的,正好可以用二次探測定理,
如果(x^2)%n==1,也就是y等於1的時候,假如n是素數,那么x==1||x==n-1,如果x!=1&&x!=n-1,那么n肯定不是素數了,返回false。
8.運行到這里的時候x=a^(n-1),根據費馬小定理,x!=1的話,肯定不是素數了,返回false
9.因為Miller-Rabin得到的結果的正確率為 75%,所以要多次循環步驟4~8來提高正確率
10.循環多次之后還沒返回,那么n肯定是素數了,返回true
下面是模板:

const ll S = 8; ll mult_mod(ll a, ll b, ll c) { a %= c; b %= c; ll ret = 0; ll tmp = a; while (b) { if (b & 1) { ret += tmp; if (ret > c) ret -= c; } tmp <<= 1; if (tmp > c)tmp -= c; b >>= 1; } return ret; } ll pow_mod(ll a, ll n, ll mod) { ll ret = 1; ll temp = a % mod; while (n) { if (n & 1)ret = mult_mod(ret, temp, mod); temp = mult_mod(temp, temp, mod); n >>= 1; } return ret; } bool check(ll a, ll n, ll x, ll t) { ll ret = pow_mod(a, x, n); ll last = ret; for (ll i = 1; i <= t; i++) { ret = mult_mod(ret, ret, n); if (ret == 1 && last != 1 && last != n - 1)return true; last = ret; } if (ret != 1)return true; else return false; } bool Miller_Rabin(ll n) { if (n < 2)return false; if (n == 2)return true; if ((n & 1) == 0)return false; ll x = n - 1; ll t = 0; while ((x & 1) == 0) { x >>= 1; t++; } srand(time(NULL)); for (ll i = 0; i < S; i++) { ll a = rand() % (n - 1) +1; if (check(a, n, x, t)) return false; } return true; }
#include<cstdlib> #include<ctime> #include<cstdio> using namespace std; const int count=10; int modular_exp(int a,int m,int n) { if(m==0) return 1; if(m==1) return (a%n); long long w=modular_exp(a,m/2,n); w=w*w%n; if(m&1) w=w*a%n; return w; } bool Miller_Rabin(int n) { if(n==2) return true; for(int i=0;i<count;i++) { int a=rand()%(n-2)+2; if(modular_exp(a,n,n)!=a) return false; } return true; } int main() { srand(time(NULL)); int n; scanf("%d",&n); if(Miller_Rabin(n)) printf("Probably a prime."); else printf("A composite."); printf("\n");
1 const ll S = 8; 2 ll mult_mod(ll a, ll b, ll c) { 3 a %= c; 4 b %= c; 5 ll ret = 0; 6 ll tmp = a; 7 while (b) { 8 if (b & 1) { 9 ret += tmp; 10 if (ret > c) ret -= c; 11 } 12 tmp <<= 1; 13 if (tmp > c)tmp -= c; 14 b >>= 1; 15 } 16 return ret; 17 } 18 ll pow_mod(ll a, ll n, ll mod) { 19 ll ret = 1; 20 ll temp = a % mod; 21 while (n) { 22 if (n & 1)ret = mult_mod(ret, temp, mod); 23 temp = mult_mod(temp, temp, mod); 24 n >>= 1; 25 } 26 return ret; 27 } 28 bool check(ll a, ll n, ll x, ll t) { 29 ll ret = pow_mod(a, x, n); 30 ll last = ret; 31 for (ll i = 1; i <= t; i++) { 32 ret = mult_mod(ret, ret, n); 33 if (ret == 1 && last != 1 && last != n - 1)return true; 34 last = ret; 35 } 36 if (ret != 1)return true; 37 else return false; 38 } 39 bool Miller_Rabin(ll n) { 40 if (n < 2)return false; 41 if (n == 2)return true; 42 if ((n & 1) == 0)return false; 43 ll x = n - 1; 44 ll t = 0; 45 while ((x & 1) == 0) { 46 x >>= 1; 47 t++; 48 } 49 50 srand(time(NULL)); 51 52 for (ll i = 0; i < S; i++) { 53 ll a = rand() % (n - 1) +1; 54 if (check(a, n, x,