质因子进化

· · 个人记录

174267日,哥德巴赫写信给欧拉,提出了以下的猜想:任何一个大于9的奇数都可以表示成3个质数之和。

欧拉在回信中说,他相信这个猜想是正确的,但他不能证明。

从此,这道数学难题引起了几乎所有数学家的注意。哥德巴赫猜想由此成为数学皇冠上一颗可望不可及的“明珠”。

题目内容表述

先给出一个奇数,要求输出3个质数,这 3 个质数之和等于输入的奇数。

编一个程序验证哥德巴赫猜想。

输入仅有一行,包含一个在long long范围内正奇数,。

输出仅有一行,输出3个质数,这3个质数之和等于输入的奇数。相邻两个质数之间用一个空格隔开,最后一个质数后面没有空格。如果表示方法不唯一,请输出第一个质数最小的方案,如果第一个质数最小的方案不唯一,请输出第一个质数最小的同时,第二个质数最小的方案。

以下是我的代码:

#include<bits/stdc++.h>
using namespace std;
long long n;
bool zhi(long long x){//是否为质数 
    if(x<2||x%2==0&&x!=2||x%3==0&&x!=3||x%5==0&&x!=5||x%7==0&&x!=7||x%11==0&&x!=11||x%13==0&&x!=13)
    return 0;
    if(x<4||x==5||x==7||x==11||x==13)
    return 1;
    if(x<17)
        return 0;
    for(long long i=18;i-1<=sqrt(x)&&i-1<=x/17;i+=6){
    if(i-1<=x/17&&x%(i-1)==0)
            return 0;
    if(i+1<=sqrt(x)&&i+1<=x/17&&x%(i+1)==0)
        return 0;
    }
    return 1;
}
int main(){
    cin>>n;
    if(zhi(n-4)){
    cout<<"2 2 "<<n-4;
    return 0;
    }
    for(long long i=3;i<=n/3;i+=2)
    for(long long j=i;j<=(n-i)/2;j+=2)
            if(zhi(i)&&zhi(j)&&zhi(n-i-j)){
            cout<<i<<" "<<j<<" "<<n-i-j;
        return 0;
        }
    return 0;
}

再做优化:

#include<bits/stdc++.h>
using namespace std;
long long n;
bool zhi(long long x){//是否为质数 
    if(x<2||x%2==0&&x!=2||x%3==0&&x!=3||x%5==0&&x!=5||x%7==0&&x!=7||x%11==0&&x!=11||x%13==0&&x!=13)
    return 0;
    if(x<4||x==5||x==7||x==11||x==13)
    return 1;
    if(x<17)
        return 0;
    for(long long i=18;i-1<=sqrt(x)&&i-1<=x/17;i+=6){
    if(i-1<=x/17&&x%(i-1)==0)
            return 0;
    if(i+1<=sqrt(x)&&i+1<=x/17&&x%(i+1)==0)
        return 0;
    }
    return 1;
}
int main(){
    cin>>n;
    if(zhi(n-4)){
    cout<<"2 2 "<<n-4;
    return 0;
    }
    cout<<"3 ";
    for(long long i=3;i<=n/3;i+=2)
        if(zhi(i)&&zhi(n-i-3)){
        cout<<j<<" "<<n-i-j;
        return 0;
    }
    return 0;
}

再做那么一点点优化:

inline bool zhi(long long x){
    if(x>4&&x%6%4!=1||x<2||x%2==0&&x!=2||x%3==0&&x!=3||x%5==0&&x!=5||x%7==0&&x!=7||x%11==0&&x!=11||x%13==0&&x!=13)
    return 0;
    if(x<4||x==5||x==7||x==11||x==13)
    return 1;
    if(x<17)
    return 0;
    for(long long i=18;i-1<=sqrt(x)&&i-1<=x/17;i+=6){
    if(i-1<=x/17&&x%(i-1)==0)
            return 0;
    if(i+1<=sqrt(x)&&i+1<=x/17&&x%(i+1)==0)
        return 0;
    }
    return 1;
}

依此模板,可做质因子等题。且可优化许多,去除一些不必要的,可以依据质数是质数(没什么意义,本来就是这样的),质数之倍数,此倍数非本身之质数。而后扩倍可得结论。

但还可以做优化,思路如下:

比如,23均为质数,23为至小的两个质数。

此时,先看1的倍数,123······1不为质数,2为质数,3为质数。

22倍及以上:4681012······

32倍及以上:69121512······

23均为质数,所以除23外,只有取余2、3的最小公倍数为15的数方 可能(仅仅是有可能) 为质数。

故,除已知质数,一个数取余已知质数的最小公倍数不为任意一个已知质数之倍数,则此数可能为质数。

1至最大已知质数的二次方这个范围内,一个数取余已知质数的最小公倍数不为1至最大已知质数的任意一个质数之倍数,则此数可能为质数。

已知质数需从23,从第一个质数到第二个质数,从一个质数到下一个质数,至少可以知道1至最大已知质数的2次方中的任意正整数是否为质数,所有数都知道,不过请注意,要确定1至最大已知质数中的任意正整数是否为质数较难。

以此,可简单地不断“进化”,如“进化”算法般,但最好先确定质数2来“进化”。

此为吾所思之质之理。