其他分享
首页 > 其他分享> > 题解 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爆踩我

标签:Miller,题解,质数,Goldbach,lol,res,ll,Euler,Rabin
来源: https://www.cnblogs.com/-aday/p/solution-uva10311.html