实际发表时间: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爆踩我