題解 UVA10311 【Goldbach and Euler】
阿新 • • 發佈:2020-08-29
實際發表時間:2020-04-15
https://www.luogu.com.cn/problem/UVA10311
題目大意:
判斷一個數是不是兩個不同質數的和,然後按指定格式輸出
我們先可以判斷此數的奇偶性
如果是奇數,因為奇數只能是一奇一偶的和,偶質數又只有2,所以判斷\(n-2\)是否是質數即可
如果是偶數,我們從中間開始查詢,找到就輸出,沒有就輸出不行
那怎麼判斷呢?
兩種做法:
第一種:\(Miller\;Rabin\)
即一個一個數用\(iller\;Rabin\)判斷是否是質數
程式碼:
#include<bits/stdc++.h> #define mul(a,b,c) a*b%c using namespace std; typedef int ll; typedef long long lol; const ll prime[]={2,3,5,7,11,13,17,37}; lol qpow(lol x,lol y,lol p)//快速冪 { lol res=1; while(y) { if(y&1)res=mul(res,x,p); x=mul(x,x,p); y>>=1; } return res; } bool MillerRabin(ll n,ll a)//mr主體 { lol d=n-1,r=0; while(!(d&1))d>>=1,r++; lol z=qpow(a,d,n); if(z==1)return 1; for(int i=0;i<r;i++) { if(z==n-1)return 1; z=mul(z,z,n); } return 0; } bool Miller_Rabin(ll n)//二次探測 { if(n<=1)return 0; for(int i=0;i<8;i++) { if(n==prime[i])return 1; if(n%prime[i]==0)return 0; if(!MillerRabin(n,prime[i]))return 0; } return true; } int n; int main() { while(~scanf("%d",&n))//輸入 { printf("%d is ",n); if(n<5) { puts("not the sum of two primes!"); continue; } if(n%2)//奇數 { if(!Miller_Rabin(n-2))puts("not the sum of two primes!"); else printf("the sum of 2 and %d.\n",n-2); continue; } int i=(n>>1); bool flag=1; while(i--) {//查詢 if(!Miller_Rabin(i))continue; if(Miller_Rabin(n-i)) { printf("the sum of %d and %d.\n",i,n-i); flag=0; break; } } if(flag)puts("not the sum of two primes!"); } return 0; }
第二種:尤拉篩
預處理即可,應該會更快,但我用了Miller Rabin,歡迎大佬們用xxs爆踩我