zoukankan      html  css  js  c++  java
  • 洛谷P1579.验证哥德巴赫猜想(DFS+素性测试)

    题目背景

    1742年6月7日哥德巴赫写信给当时的大数学家欧拉,正式提出了以下的猜想:任何一个大于9的奇数都可以表示成3个质数之和。质数是指除了1和本身之外没有其他约数的数,如2和11都是质数,而6不是质数,因为6除了约数1和6之外还有约数2和3。需要特别说明的是1不是质数。

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

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

    题目描述

    现在请你编一个程序验证哥德巴赫猜想。

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

    输入格式

    仅有一行,包含一个正奇数n,其中9<n<20000

    输出格式

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

    输入输出样例

    输入 #1

    2009

    输出 #1

    3 3 2003


     
     
     

    我的分析

    此题就是暴力递归搜索,本身没什么难度,但是如果用常规的枚举2到sqrt(n)之间的数来对n进行素性检测的方法,最后一个样例就过不了!重要的事情说三遍,过不了!过不了!过不了!(超凶╭(╯^╰)╮)
    于是,我又去网上找了一个改进后的素性测试方法(虽然搞不懂什么原理O(∩_∩)O),然后成功地通过了所有样例

    #include<iostream>
    #include<cmath>
    #include<cstring>
    using namespace std;
    //素性检测函数
    bool isprime(int n){
        int p[8]={4,2,4,2,4,6,2,6};
        int i=7,j,q;
        if(n==1)return 0;
        if(n==2||n==5||n==3)return 1;
        if(n%2==0||n%3==0||n%5==0)return 0;
        q=(int)sqrt(n);
        for(;i<=q;){
            for(j=0;j<8;j++){
                if(n%i==0)return 0;
                i+=p[j];
            }
            if(n%i==0)return 0;
        }
        return 1;
    }
    //tmp数组用来暂时缓存可能成为答案的3个数,res数组用来储存最终答案的3个数
    int res[4],tmp[4];
    void dfs(int n,int count){
    //如果已经积累到2个素数了,那么本轮递归传入的n就是剩下的一个数了
    //若n为素数,则产生一组可能答案,以下步骤尝试更新最终结果
        if(count==2&&isprime(n)){
            tmp[++count]=n;
            if(tmp[1]<res[1]){
                res[1]=tmp[1];
                res[2]=tmp[2];
                res[3]=tmp[3];
            }
            else if(tmp[1]==res[1]){
                if(tmp[2]<res[2]){
                    res[1]=tmp[1];
                    res[2]=tmp[2];
                    res[3]=tmp[3];
                }
            }
            return;
        }
        //若已经积累2个素数,而剩下的一个数非素数,则返回
        else if(count==2) return;
        for(int i=2;i<n;++i){
            if(isprime(i)){
                tmp[++count]=i;
                dfs(n-i,count);
                count--; //注意递归返回后计数器也一定要跟着复原
            }
        }
    }
    int main(){
    	//初始化两个数组,注意初始时res比所给的数大,而tmp一定要比res大
        memset(res,20001,sizeof(int)*4);
        memset(tmp,20002,sizeof(int)*4);
        int n;
        cin>>n;
        dfs(n,0);
        cout<<res[1]<<" "<<res[2]<<" "<<res[3];
        return 0;
    }
    
  • 相关阅读:
    [LeetCode] 146. LRU Cache(LRU 缓存)
    [LeetCode] 55. Jump Game(跳跃游戏)
    [LeetCode] 33. Search in Rotated Sorted Array(搜索旋转有序数组)
    [LeetCode] 19. Remove Nth Node From End of List(从单链表中移除倒数第 n 个节点)
    [LeetCode] 79. Word Search(单词查找)
    [LeetCode] 322. Coin Change(换硬币)
    [LeetCode] 34. Find First and Last Position of Elements in Sorted Array(在有序数组中寻找某个元素第一次和最后一次出现的位置)
    第04组 Alpha冲刺(2/6)
    第04组 Alpha冲刺(1/6)
    第04组 团队Git现场编程实战
  • 原文地址:https://www.cnblogs.com/lonelyprince7/p/12247402.html
Copyright © 2011-2022 走看看