引用
啰嗦
起初没想明白,居然想着用dfs一个个枚举出等差数列,突然一想,这并不是很现实的。首先你并不知道起始位置在哪,其次公差你也不清楚,所以单是前几个数的排列就够你等的了。有兴趣验证的小伙伴可以试试我的代码,应该是没有问题的,不过懒得等了~
后来看了别人的题解后,发现其实自己一开始就把问题想复杂了。并不需要找排列,只需要确定起始位置是不是素数,然后从公差2开始遍历,寻找后九个数字。由题目的性质我们可以知道,虽然它是填空题,但也肯定能在1~2秒就能跑完,所以数据范围可以定在1e5,而公差可以定在1000以内。
接下来就是判断素数了,可以用线性筛或埃式筛等算法预处理好所有素数,抑或是一个个判断都是可以的(利用它的一对因子中大因子不会大于它的算术平方根 ),也叫试除法
题目描述
2,3,5,7,11,13,… 是素数序列。 类似:7,37,67,97,127,157 这样完全由素数组成的等差数列,叫等差素数数列。
上边的数列公差为 30,长度为 6。
2004 年,格林与华人陶哲轩合作证明了:存在任意长度的素数等差数列。 这是数论领域一项惊人的成果!
有这一理论为基础,请你借助手中的计算机,满怀信心地搜索:
长度为 10 的等差素数列,其公差最小值是多少?
样例
无样例
算法
(线性筛) O ( n ) O(n) O(n)
利用线性筛将素数存到一个数组中,被筛的数存到另一个数组中。
判断的时候直接把起始位置的值当做 a n = a 1 + ( n − 1 ) k a_n = a_1 + (n - 1)k an=a1+(n−1)k 中的 a 1 a_1 a1 , t + j ∗ k t + j * k t+j∗k 也就是 a n a_n an ,将其作为索引判断后面九个数是否为素数,如果九个都满足那么此时的公差就是最小公差。
(试除法判断素数) O ( n ) O(\sqrt{n}) O(n)
跟判断质数一样,最多判断 ( n ) \sqrt(n) (n) 次
这里的做法和上面类似,直接看代码吧,稍微有一点区别
C++代码
// 线性筛
include <iostream>
using namespace std;
const int N = 1e5 + 10;
int primes[N] , cnt; // primes[]存储所有素数
bool st[N]; // st[x]存储x是否被筛掉
int flag;
int i , j , k;
void get_primes(int n)
{
for (int i = 2; i <= n; i ++ )
{
if (st[i]) continue;
primes[cnt ++ ] = i;
for (int j = i + i; j <= n; j += i)
st[j] = true;
}
}
int main()
{
get_primes(100000);
for ( i = 0; i < 1000; i ++ ) {
int t = primes[i];
for ( j = 2; j < 1000; j ++ ) {
for ( k = 1; k < 10; k ++ ) {
if (st[t + j * k]) {
break;
}
}
if (k == 10) {
cout << j;
return 0;
}
}
}
return 0;
}
#include<iostream>
#include<cmath>
using namespace std;
bool isPrimeNumber(int t);
int main() {
bool flag = true;
for (int i = 2; i < 1000; i++) { // i:起始的素数
for (int j = 2; j < 1000; j++) { // j:等差数列公差
flag = true;
for (int k = 0; k < 10; k++) { // k:第k个素数
if (!isPrimeNumber(i + j * k)) { // 判断等差数列中的数字是否为素数
flag = false;
break;
}
}
if (flag) { cout << j; break; } // 输出结果
}
}
return 0;
}
/*
** 判断一个数是否为素数,是则返回true,否则返回false
*/
bool isPrimeNumber(int t) {
for (int i = 2; i <= sqrt(t); i++) {
if (t % i == 0)
return false;
}
return true;
}
// 暴力枚举
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int primes[N], cnt; // primes[]存储所有素数
bool st[N]; // st[x]存储x是否被筛掉
int n = 10;
int perm[N];
int len;
// 线性筛法求素数
void get_primes(int n)
{
for (int i = 2; i <= n; i ++ )
{
if (st[i]) continue;
primes[cnt ++ ] = i;
for (int j = i + i; j <= n; j += i)
st[j] = true;
}
}
// dfs排列型枚举
void dfs(int u , int start)
{
if(u + len - start < n) return;
if(u > n)
{
int tmp = perm[2] - perm[1] , cnt1 = 1;
for(int i = 3; i <= n; i ++){
if (perm[i] - perm[i - 1] != tmp) break;
else cnt1++;
}
if (cnt1 == 9) {
for (int i = 1; i <= n; i ++)
printf("%d", perm[i]);
puts("");
}
return ;
}
for(int i = start; i < len; i++)
{
perm[u] = primes[i];
dfs(u + 1 , i + 1);
perm[u] = 0;
}
}
int main()
{
// 请在此输入您的代码
get_primes(100000);
len = cnt - 1;
dfs(1 , 0);
return 0;
}