Usaco第1.6节主要回文

Usaco Section 1.6 Prime Palindromes

本文关键字:回文 6节 Usaco      更新时间:2023-10-16

你好,所以我在做这个问题,他们给你的范围从最小值5到最大值100000000

你必须找到从第一个数字到第二个数字的所有素数回文

示例:

输入:500

输出:

5

7

11

101

131

151

181

191

313

353

373

383

所以在你看我的解决方案之前,你需要了解两件事,除了第一个素数之外,所有素数都以这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;
}

所以问题是,如果两个程序都做同样的事情,但我做这个程序的次数比他少,为什么我的程序没有时间,而他的程序没有?

事实上,正如一些评论所暗示的那样,问题是我的素数,如果首先检查许多数字的2和3的可除性,那么解决方案如下:

#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;
}