写一次题解,是2021PAT甲级春季的真题,我今年考过,但是不是很理想,做到第三题,实在不会堆排序,直接交卷了,真是很遗憾。后来状态一直不是很好,买了acwing的网课,看了一段时间,yxc真的很强,代码老练沉稳简洁。我一直偷懒用STL的,人家大佬一直手写,但还是比代码便秘的我,更短更强。
今天回顾一下,九月再考一次吧。
题意:
求一个size为n的素数等差数列,最大上边界为maxp,如果有多个,则取公差最大的,如果还有多个,取首项最大的.找不到就输出范围内最大素数。
思路:
用线性筛或者埃筛打一个素数表,降低一下遍历的复杂度。
然后从大到小枚举MAXP范围内的所有的素数。
等差从大到小枚举,如果能组成完整素数列,则更新我的数据,更新的唯一标准就是新素数列的公差比我更大,因为我已经保证了首项是从大到小的。
d≤MAXP−a/n−1,对n=1,特判一下,防止除零异常。
//
// Created by 江左 on 2021/8/18.
//
#include <iostream>
#include <vector>
const int N=100010;
using namespace std;
int n,p,dmax=-1,res;
vector<int> primes; //记忆下,范围内的素数
bool st[N]; // st[x]存储x是否被筛掉
void get_primes(int n)
{
for (int i = 2; i <= n; i ++ )
{
if (!st[i]) primes.push_back(i);
for (int j = 0; primes[j] <= n / i; j ++ )
{
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
int main()
{
scanf("%d %d",&n,&p);
get_primes(p);
if(n==1) {
cout<<primes.back();return 0;
}
for(int i=primes.size()-1;i>=0;i--)
{
int a=primes[i];//首项
for (int d = (p-a)/(n-1); d >=1 ; --d) {
//d是公差
bool f= true;
int cnt=n-1,t=a;
while(cnt--)
{
t+=d;
if(st[t])//a[i]需要
{
f=false;break;
}
}
if(f)
{
if(d>dmax) dmax=d,res=a;
break;
}
}
}
if(dmax==-1