X轴上10^8个点,从左到右依次编号为0~10^8-1,相邻点距离为1,其中有n个点有特殊意义,从小到大依次为a0~an-1,其中保证a0=0.
现在需要建设收集站,有两个要求必须被满足:1、每个有意义的点必须修建收集站。
2、相邻收集站的距离必须为1或为某个质数。
现给出n和a数组,求需要建设收集站的最小数量。
3,[0,7,11]
4
在0,7,8,11处建造收集站,差值分别为7,1,3,符合要求
输入数据包含一个数n和一个长度为n的数组a,数组a的下标为0~n-1,保证a数组递增,且a0=0。
输出一个整数,表示答案。
1<=n<=1000,a数组中数值保证小于10^8
根据题意,车站数最少是n
,如果相邻两个车站的距离不是1或素数,就需要在中间插入一个或多个车站来使每个车站之间的距离都是1或素数,也就是求把一个非素数分解为素数的个数,可以想到哥德巴赫猜想。
维基百科:哥德巴赫猜想
对每个车站之间的距离进行判断,如果不是1或素数,就需要进行分解。如果距离是偶数,那么最多只需要新增一个车站;如果是奇数,最多需要新增两个车站,但也有只需要新增一个车站的例子,比如9=2+7
和15=2+13
。如果想把一个奇数分解为两个素数,就必须是一个奇素数、一个偶素数,偶素数只有2
,所以先判断一下-2
之后能不能得到素数,如果能,只需要新增1
个车站;如果不能,那么由哥德巴赫猜想,-2
之后的奇数也一定能分解成2
个素数,所以需要新增 2
个车站。
class Solution { public: /** * * @param n int整型 * @param a int整型一维数组 * @param aLen int a数组长度 * @return int整型 */ int work(int n, int* a, int aLen) { int count = n; for (int i = 1; i < n; i++) { int dist = a[i] - a[i - 1]; if (dist != 1 && !isprime(dist)) { if (dist % 2 == 0 || isprime(dist - 2)) count += 1; else count += 2; } } return count; } private: bool isprime(int n) { if (n == 1) return false; for (int i = 2; i * i <= n; i++) if (n % i == 0) return false; return true; } };
class Solution { public: /** * * @param n int整型 * @param a int整型一维数组 * @param aLen int a数组长度 * @return int整型 */ int work(int n, int* a, int aLen) { int ans = n; for(int i=1;i<n;i++) { int val = a[i] - a[i-1]; if(isOk(val)) { continue; } else if(!(val&1)) { ans += 1; } else if(isOk(val-2)) { ans += 1; } else { ans += 2; } } return ans; } bool isOk(int v) { if(v==1 || v==2) return true; for(int i=2;i*i<=v;i++) { if(v%i==0) return false; } return true; } };
这题居然用到了哥德巴赫猜想,真的秀到我了!
讲讲思路吧,首先每个牛牛所在村庄都要建一座车站,我们就将结果ret
初始化为牛牛村庄的数量aLen
。接下来就是计算每两个牛牛村庄之间的距离,如果为质数(或称素数),则不用在这两个村庄之间再修建车站;如果为非质数,就要分几种情况进行讨论(不妨设某两个村庄距离为为len
):
len
为偶数,则可拆非为两个质数之和,意思就是在这两个村庄之间再修一座车站,ret++
即可; len
为奇数,则将将len
拆分为len = (len - 2) + len
,此时对于len-2
,需要再分两种情况讨论:len-2
为质数,则len
就是len-2
和2
两个质数之和,意思就是在这两个村庄之间再修一座车站,ret++
即可;len-2
为非质数,则可将len-2
拆分成2个质数之和,进一步可将len
拆分为3个质数之和,意思就是在这两个村庄之间再修两座车站,ret+=2
即可。//一开始使用贪心,错误,看了题解后才使用哥德巴赫猜想 class Solution { private: int res; public: int work(int n, int* a, int aLen) { res = 1; for (int i = 1; i < aLen; i++) { int distance = a[i] - a[i - 1]; if (is_prime(distance)) res++; else { if (distance % 2 == 0) res += 2; else { if (is_prime(distance - 2)) res += 2; else res += 3; } } } return res; } bool is_prime(int n) { for (int i = 2; i <= sqrt(n); i++) if (n % i == 0) return false; return true; } };
bool isprime(int num){ if(num==1) return true; for(int i=2;i*i<=num;i++){ if (num%i==0) return false; } return true; } int separate(int num) { if (isprime(num)) //判断是否为素数 return 1; else { if (num % 2 == 0) //判断是否为偶数 return 2; else { if (isprime(num - 2)) //判断n-2是否为素数 return 2; else return 3; } } } int work(int n, int* a, int aLen) { // write code here int ans =0; int length[2*n]; for(int i=0;i<n-1;i++){ length[i]=a[i+1]-a[i]; if(isprime(length[i]))ans++; else ans += separate(length[i]); } return ans+1; }
class Solution { public: /** * * @param n int整型 * @param a int整型一维数组 * @param aLen int a数组长度 * @return int整型 */ isPrime(int x){ for(int i=2;i*i<=n;i++) if(x%i==0) return false; return true; } int work(int n, int* a, int aLen) { int cnt = 1, d; for(int i=1;i<n;i++){ d = a[i] - a[i-1]; if(isPrime(d)) cnt++; else{ if(d&1){ if(isPrime(d-2)) cnt += 2; else cnt += 3; }else cnt += 2; } } return cnt; } };
import java.util.*; public class Solution { /** * * @param n int整型 * @param a int整型一维数组 * @return int整型 */ public int work (int n, int[] a) { int count = 1,len = 0; for(int i=1; i<a.length; i++) { len = a[i] - a[i-1]; if(isPrime(len)) { count++; } else if(len % 2 == 0 || isPrime(len-2)) { count += 2; } else { count += 3; } } return count; } private boolean isPrime(int num) { for(int i=2; i * i <= num; i++) { if(num % i == 0) { return false; } } return true; } }
首先所有Ai均有车站,接下来判断距离是否为质数或1,是则车站数+1,否则继续判断距离;
当距离为偶数时,可以表示为两个质数的和(根据哥德巴赫猜想);
当距离为奇数时,分解为p=(p-2)+2:
若p-2为质数,则可表示为两个质数的和
若p-2为非质数,则可表示为三个质数的和
class Solution: def work(self , n , a ): # write code here count = n dis = [(i-j)for i,j in zip(a[1:],a)] for i in dis: if( i!=1 and self.isPrimeNumber(i)==False): if(i%2==0 or self.isPrimeNumber(i-2)): count+=1 else: count+=2 return count def isPrimeNumber(self,x): flag = True if(x==1): flag = False for i in range(2,int(x)): if(x%i==0): flag=False break return flag
class Solution { public: /** 任一大于2的偶数都可写成两个质数(素数)之和 任一大于5的整数都可写成三个质数(素数)之和 首先建立n个车站(牛牛所在村庄) 然后判断两个车站的距离dis是不是素数, 如果是素数,两个车站之间不用再增加车站; 如果dis不是素数,分两种情况(偶数和奇数); 如果dis是偶数(此时dis大于2),有任一大于2的偶数可以写成两个素数之和,所以在两个车站之间再增加一个车站即可; 如果dis是奇数,奇数 = 奇数 + 偶数,。有任一大于5的整数都可写成三个质数(素数)之和,有2即是偶数又是素数, 如果dis-2是素数,那么说明dis = 素数 + 2(素数),此时只用增加一座车站即可:n + 1; 如果dis-2不是素数,有任一大于5的整数都可写成三个质数(素数)之和,知只要在两个车站之间建立两个车站即可:n + 2 **/ int isPrime(int number) { if (number==1||number==2) { return 1; }else { for (int i=2; i<=number/2; i++) { if(number % i == 0) { return 0; //不是素数 } } } return 1; //是素数 } /** * @param n int整型 * @param a int整型一维数组 * @param aLen int a数组长度 * @return int整型 */ int work(int n, int* a, int aLen) { // write code here for (int i=0; i<aLen-1; i++) { if (isPrime(a[i+1] - a[i])==1) { continue; }else { if((a[i+1] - a[i])%2 == 0) { n += 1; }else { if(isPrime(a[i+1] - a[i] - 2)==1) { n += 1; }else { n += 2; } } } } return n; } };
哥德巴赫猜想: 1、大于2的偶数,可以表示为两个质数的和;