题意概述
- 对数轴上的n个点,必须建立收集站
- 相邻两收集站的距离若不为素数或1,则在其中间尽量少的建立若干收集站使其满足条件
- 欲求解最少建立收集站的个数
方法一:哥德巴赫猜想
思路与具体做法
哥德巴赫猜想——引自百度百科
“强哥德巴赫猜想”或“关于偶数的哥德巴赫猜想”:任一大于2的偶数都可写成两个素数之和
“弱哥德巴赫猜想”或“关于奇数的哥德巴赫猜想”:任一个大于7的奇数都能被表示成三个奇质数的和
- 若两站之间距离为素数或1:
- 则两站间不需修站
- 若两站之间距离为偶合数:
- 根据强哥德巴赫猜想,大于2的偶数距离间都不需要修建(小于等于2的偶数只有2,为素数)
- 若两站之间距离为奇合数:
- 因为奇数只可以拆分成奇数+偶数,现在要求拆分出的这两段子距离也都是素数,而2是唯一的偶数的素数,所以此时若拆分出来的奇数也是素数,则两站间最少修建一个站台
- 若不满足上述情况,根据弱哥德巴赫猜想,大于7的奇数距离都至少能被拆分成3个奇质数,(小于等于7的奇数满足素数或1的情况)
class Solution {
public:
bool isprime(int n){
if(n==1)return true;//判断1
for(int i=2;i*i<=n;i++){//判断素数
if(n%i==0)return false;
}
return true;
}
int work(int n, int* a, int aLen){
int ans=1;//第一个站一定要建
for(int i=1;i<n;i++){//从第二个站开始遍历
int distance=a[i]-a[i-1];
if(isprime(distance))ans++;//两站距离为素数,则直接建立该站,两站间不需再建站
else{//两站距离为合数
if(distance%2==0)ans+=2;//偶合数,强哥德巴赫猜想
else{//奇合数
if(isprime(distance-2))ans+=2;//奇数=奇数+偶数,拆分
else ans+=3;//弱哥德巴赫猜想
}
}
}
return ans;
}
};时间复杂度和空间复杂度分析
时间复杂度: , n为点数,
为一次判断素数的最大时间复杂度
空间复杂度: ,仅用到了一个整形变量ans用于记录车站数量
方法二:动态规划(超时)
思路与具体做法
- dp[i]:长度为i的距离内可新建的站数目
- 首先计算题目中已给的两站间最大距离
- 接着枚举所有站间距离,直到站间最大距离
- 对每一个站间距离
- 为素数,说明这段站间距离i不需要新建站
- 为合数,则对这段站间距离i进行转态转移
- 转态转移:
- 从距离1开始枚举站间距离的所有素数j,对站间距i,
- 若它不进行分割,站间距离i不变,可新建的站数目不变,
- 若它可进行分割,站间距离i减少j,可新建的站数目加1,
- 若它不进行分割,站间距离i不变,可新建的站数目不变,
- 从距离1开始枚举站间距离的所有素数j,对站间距i,
- 注意:
- 因为需要枚举一段距离内的所有素数,所以这里会超时,即使用欧拉筛法进行打表,得到一个素数表,也会出现运行超时的情况
class Solution {
public:
int pNum=0;//素数个数
void Find_Prime2(int maxn,int p[],int prime[]){
for(int i=2;i<maxn;i++){
if(p[i]==false){
prime[pNum++]=i;
}
for(int j=0;j<pNum&&i*prime[j]<maxn;j++){//遍历每一个已找到的素数
p[i*prime[j]]=true;//这个素数的倍数是合数
if(i%prime[j]==0)break;//因为每个数只被它的最小质因子筛一次,在此之后的质数不用筛
}
}
}
int work(int n, int* a, int aLen) {
int maxx=1;//两站间的最大距离
for(int i=1;i<n;i++){
maxx=max(maxx,a[i]-a[i-1]);
}
int p[maxx+1];//初始都是素数
memset(p,0,sizeof(p));
int prime[maxx+1];//素数表
Find_Prime2(maxx+1,p,prime);//打表,表长为两点之间最长距离
int dp[maxx+1];//两站需建多少站点
for(int i=1;i<=maxx;i++){
if(!p[i]||i==1){//距离为素数,中间不用建站
dp[i]=0;
}else{//距离不为素数
dp[i]=0x3fffffff;
for(int j=1;j<=i;j++){
if(!p[j]){
dp[i]=min(dp[i],dp[i-j]+1);
}
}
}
}
int ans=n;
for(int i=1;i<n;i++){
ans+=dp[a[i]-a[i-1]];
}
return ans;
}
};
时间复杂度和空间复杂度分析
时间复杂度:,d为站间最大距离,dp数组求解两层循环
空间复杂度:,d为站间最大距离,这里仅用到了一个长度为d+1的dp数组

京公网安备 11010502036488号