Usaco 第 1.6 节 Prime Palindromes
Posted
技术标签:
【中文标题】Usaco 第 1.6 节 Prime Palindromes【英文标题】:Usaco Section 1.6 Prime Palindromes 【发布时间】:2020-07-09 03:09:28 【问题描述】:你好,所以我在做这个问题,他们给你的范围从最小值 5 到最大值 100,000,000
你必须找到从第一个数字到第二个数字的所有素数回文
示例:
输入:5 500
输出:
5
7
11
101
131
151
181
191
313
353
373
383
因此,在您查看我的解决方案之前,您需要了解 2 件事,除了一些第一个素数之外,所有素数都以这 4 位数字 1、3、7、9 结尾,并且所有具有偶数位数的回文数都是能被 11 整除
了解这一点,您就知道所有素数回文数都需要以这 4 位数字之一开头,并且没有偶数位数的素数回文数,例如:7557
所以我的解决方案是创建回文并检查它们是否为素数,然后打印它们,我过去检查它们的方法是使用像 12 这样的数字,然后将其反转并像 1221 一样附加它并在中心从1到9:12121
但我这样做的方式是让所有数字都以这种方式以这 4 位数字开头:
来自1-1 3-3 7-7 9-9
10-19 30-39 70-79 90 99
我这样做直到产生的数字大于限制,在这种情况下我停止创建新的回文数,这样做的好处是我把它们按顺序排列了
创建我的解决方案:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef vector < long long > vi;
typedef pair < long long, long long > pi;
typedef vector < pi > vpi;
ifstream fin("pprime.in");
ofstream fout("pprime.out");
int reverse2(int num, int middle)
int i, save = num, digit, combino = 1;
for (i = 0; num; num /= 10)
digit = num % 10;
i = 10 * i + digit;
combino *= 10;
return i + 10 * combino * save + combino * middle;
bool prime(int n)
if (n <= 1)
return false;
for (int i = 2; i < n; i++)
if (n % i == 0)
return false;
return true;
bool solve(int i, int n, int m, int digits)
int c, b;
c = reverse2(i, 0);
for (int j = 0; j <= 9; j++)
b = c + j * digits;
if (b >= n && b <= m)
if (prime(b))
fout << b << endl;
if (b > m)
return 0;
return 1;
int main()
int n, m;
fin >> n >> m;
if (5 >= n && 5 <= m)
fout << 5 << endl;
if (7 >= n && 7 <= m)
fout << 7 << endl;
if (11 >= n && 11 <= m)
fout << 11 << endl;
int arr[4] = 1,3,7,9;
bool b = 0;
int digits = 10;
while (!b)
for (int j = 0; j < 4; j++)
int s = arr[j];
int actualdigit = arr[j] * digits / 10;
for (int i = actualdigit; i < (actualdigit/ s) * (s + 1); i++)
bool a = solve(i, n, m, digits);
if (!a)
b = 1;
j = 20;
break;
digits *= 10;
return 0;
这里的问题是我的解决方案用完了时间,例如在这种情况下:9878210 9978210
即使我使用的反向函数是从另一个也解决问题的解决方案中获得的
其他人的代码:
#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>
int primelist[100000];
int nprimes;
int isPrime(int num);
int reverse2(int i, int j);
int compare(const void *p, const void *q) return *(int *)p-*(int *)q;
void main (void)
ifstream infile("pprime.in");
ofstream outfile("pprime.out");
int i, j, begin, end, num;
infile>>begin>>end;
if (begin <= 11 && 11 <=end)
primelist[nprimes++] = 11;
for (j = 0; j <= 999; j++)
for (i = 0; i <= 9; i++)
num = reverse2(j,i);
if (num >= begin && num <=end && isPrime(num))
primelist[nprimes++] = num;
qsort(primelist, nprimes, sizeof(int), compare);
for (i = 0; i < nprimes; i++)
outfile << primelist[i] << "\n";
int
reverse2(int num, int middle)
int i, save=num, digit, combino = 1;
for (i = 0; num; num /= 10)
digit = num % 10;
i = 10 * i + digit;
combino *= 10;
return i+10*combino*save+combino*middle;
int isPrime(int num)
int i;
if (num <= 3) return 1;
if (num%2 == 0 || num%3 ==0) return 0;
for (i = 5; i*i <= num; i++)
if (num %i ==0)
return 0;
return 1;
所以问题是为什么我的程序会超时而他却没有,如果两者都做同样的事情,但我做的程序比他少?
【问题讨论】:
仅将第一行替换为标准包含。然后删除接下来的 17 行,不要写那样的东西。然后给你所有的变量更长的名字。然后将更容易找到错误。 请格式化您的代码并去掉很多空白行,以使其与其他人的代码保持一致。此外,将他的主要棋子与您的进行比较。 【参考方案1】:实际上,正如一些 cmets 所暗示的那样,问题是我的主要功能,如果首先检查可被 2 和 3 整除 2 很多数字的非常常见的因数,那么它的解决方案将如下所示:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef vector < long long > vi;
typedef pair < long long, long long > pi;
typedef vector < pi > vpi;
ifstream fin("pprime.in");
ofstream fout("pprime.out");
int reverse2(int num, int middle)
int i, save = num, digit, combino = 1;
for (i = 0; num; num /= 10)
digit = num % 10;
i = 10 * i + digit;
combino *= 10;
return i + 10 * combino * save + combino * middle;
bool prime(int num)
int i;
if (num <= 3) return 1;
if (num%2 == 0 || num%3 ==0) return 0;
for (i = 5; i*i <= num; i++)
if (num %i ==0)
return 0;
return 1;
bool solve(int i, int n, int m, int digits)
int c, b;
c = reverse2(i, 0);
for (int j = 0; j <= 9; j++)
b = c + j * digits;
if (b >= n && b <= m)
if (prime(b))
fout << b << endl;
if (b > m)
return 0;
return 1;
int main()
int n, m;
fin >> n >> m;
if (5 >= n && 5 <= m)
fout << 5 << endl;
if (7 >= n && 7 <= m)
fout << 7 << endl;
if (11 >= n && 11 <= m)
fout << 11 << endl;
int arr[4] = 1,3,7,9;
bool b = 0;
int digits = 10;
while (!b)
for (int j = 0; j < 4; j++)
int s = arr[j];
int actualdigit = arr[j] * digits / 10;
for (int i = actualdigit; i < (actualdigit/ s) * (s + 1); i++)
bool a = solve(i, n, m, digits);
if (!a)
b = 1;
j = 20;
break;
digits *= 10;
return 0;
【讨论】:
以上是关于Usaco 第 1.6 节 Prime Palindromes的主要内容,如果未能解决你的问题,请参考以下文章
l洛谷——P1211 [USACO1.3]牛式 Prime Cryptarithm
P1217 [USACO1.5]回文质数 Prime Palindromes
luogu P1217 [USACO1.5]回文质数 Prime Palindromes x
Luogu p1217 [USACO1.5]回文质数 Prime Palindromes