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

题解 P1217 [USACO1.5]回文质数 Prime Palindromes

洛谷 P1217 [USACO1.5]回文质数 Prime Palindromes取回文数/数论/字符串