1. 程式人生 > 實用技巧 >題解 UVA10311 【Goldbach and Euler】

題解 UVA10311 【Goldbach and Euler】

實際發表時間: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爆踩我