华为机试---素数伴侣

来源:互联网 发布:守望网络初始化失败 编辑:程序博客网 时间:2024/05/20 01:07

题目描述

题目描述
若两个正整数的和为素数,则这两个正整数称之为“素数伴侣”,如2和5、6和13,它们能应用于通信加密。现在密码学会请你设计一个程序,从已有的N(N为偶数)个正整数中挑选出若干对组成“素数伴侣”,挑选方案多种多样,例如有4个正整数:2,5,6,13,如果将5和6分为一组中只能得到一组“素数伴侣”,而将2和5、6和13编组将得到两组“素数伴侣”,能组成“素数伴侣”最多的方案称为“最佳方案”,当然密码学会希望你寻找出“最佳方案”。

输入:

有一个正偶数N(N≤100),表示待挑选的自然数的个数。后面给出具体的数字,范围为[2,30000]。

输出:

输出一个整数K,表示你求得的“最佳方案”组成“素数伴侣”的对数。

 


输入描述:

输入说明1 输入一个正偶数n2 输入n个整数



输出描述:

求得的“最佳方案”组成“素数伴侣”的对数。


输入例子:
42 5 6 13

输出例子:

2


import java.util.Scanner;


public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
        while(scan.hasNext()){
            int N = scan.nextInt();
            int[] data = new int[N];
            for(int i = 0 ; i < N ; i++){
                data[i] = scan.nextInt();
            }
            printMaxPrimePartner(data , N);
        }
        scan.close();
}
/**
* 打印最佳方案素数伴侣的个数
* 算法思想:动态规划
* 题目重要条件:
* 1.N为偶数
* 2.素数伴侣成对出现,并且不能重复利用
* 题目规律(分析可能出现的情况):
* 1.相隔一个元素位置上的元素和它后面所有元素能够组成的素数伴侣的个数可能相同或者加1,
*  (1)例如2 5 6 11,2和6相隔一个元素5,6之后(包括自身)组成的素数伴侣个数是1
*    因为2和5又能够组成素数伴侣,所以2之后组成的素数伴侣为2
*  (2)例如2 4 6 11,2和6相隔一个元素5,6之后(包括自身)组成的素数伴侣个数是1
*    因为2和4不能够组成素数伴侣,所以2之后组成的素数伴侣为1
* 2.处在奇数位置(从后往前数)上的元素比他后面紧邻的一个元素的素数伴侣个数可能相同或者加1
* (1)例如2 5 6 11, 5和6是紧邻的两个元素,并且5在从后往前数第三位奇数位,
*    6之后(包括自身)组成的素数伴侣个数是1,
*    5和之后的元素没有可以组成素数伴侣的,所以5之后组成的素数伴侣为1
* (2)例如2 5 6 2, 5和6是紧邻的两个元素,并且5在从后往前数第三位奇数位,
*    6之后(包括自身)组成的素数伴侣个数是0,因为5可以与2组成素数伴侣,所以素数伴侣加1变成1
* (3)例如2 5 3 2, 5和3是紧邻的两个元素,并且5在从后往前数第三位奇数位,
*    3之后(包括自身)组成的素数伴侣个数是1,3和2组成素数伴侣
*           又因为5和2也组成素数伴侣,无非是拆开一对形成另一对,不改变素数伴侣的对数
* 3.复杂问题化简,寻找规律使用动态规划
*   (1)例如2 7 3 3 7 5 3 4 9 11,例子中2和5组成素数伴侣如果不看中间的元素7 3 3 7,
*       相当于2 5 3 4 9 11,那么2的素数伴侣的个数等于3之后组成素数伴侣的个数加1
*       如果能够计算出中间的元素7 3 3 7 对素数伴侣的影响,就可以求出最大的素数伴侣个数。
*       如果2的下标为i,5的下标为j,即求出下标在i+1到j-1之间元素对素数伴侣个数的影响
*   (2)因为是从后往前逐位按照规律更新,相邻两位元素的素数伴侣个数可能相等可能差1,即时更新
*       用result数组保存每一位与之后元素组成的素数伴侣的个数,有了如下的推导公式(瞬时)
*       result[i] = result[i + 1] - result[j - 1] + result[j + 1] + 1;
*       计算完成后,在与上一次比较后的result[i]取较大值保存
* 算法实现:
* 1.双层循环,外层从下标为length-2的元素开始递减,也就是倒数第二个
*   内层每次从下标length-1的元素开始递减,也就是倒数第一个,比较两个数的和是否为素数伴侣
* 2.从后往前逐个更新每一位能够组成的素数伴侣的个数。
* 3.result[0]就是所要求的结果
* @param data 原始数据元素
* @param length 原始数据长度
* */
private static void printMaxPrimePartner(int[] data , int length){
        int[] result = new int[length + 1];
        int count = 0;
        for(int i = length - 2 ; i >= 0 ; i--){
            for(int j = length - 1 ; j > i ; j--){
               count = isPrime(data[i] + data[j]) ? (result[i + 1] - result[j - 1] + result[j + 1] + 1) : result[i + 1];
               result[i] = Math.max(count , result[i]);
            }
        }
        System.out.println(result[0]);
    }
/**
* 判断一个数是不是素数
* 素数:又称质数,指在一个大于1的自然数中,除了1和此整数自身外,不能被(除0外)其他自然数整除的数。
* 合数:比1大但不是素数的数称为合数。1和0既非素数也非合数
* 判断方法:如果一个数n不可以被大于等于2并且小于等于根号n的数整除,则它是素数,否则是非素数
* */
private static boolean isPrime(int data){
        if(data < 2) return false;
        for(int i = 2 ; i <= Math.sqrt(data) ; i++){
            if(data % i == 0)  return false;
        }
        return true;
 }
}

1 0