USACO Section 1.5 Prime Palindromes 解题报告
题目
题目描述
题目就是给定一个区间[a,b]((5 <= a < b <= 100,000,000)),我们需要找到这个区间内所有既是回文串又是素数的数字。
输入样例
5 500
输出样例
5
7
11
101
131
151
181
191
313
353
373
383
解题思路
因为数据范围特别大,如果我们直接枚举所有的素数然后再判断是不是回文串的话肯定会超时。在题目的下面有hints,其中就告诉我们要逆向思维,既然我们枚举素数太多了,那么我们就可以先枚举出所有可能的回文串(这个数量比较少),然后再判断回文串是不是素数。下面就直接模拟这个过程就好了,在写代码的时候,主要是枚举回文串比较费劲,要细心一点。
解题代码
/*
ID: yinzong2
PROG: pprime
LANG: C++11
*/
#define MARK
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int len, alen, blen;
char astr[12],bstr[12], str[12];
bool isPrime() {
int x = 0;
int temp = 1;
// 先转化为int型整数,然后再判断是否是素数
for (int i = len-1; i >= 0; --i) {
x += (temp*(str[i]-'0'));
temp *= 10;
}
int bound = (int)sqrt(x*1.0);
for (int i = 2; i <= bound; ++i) {
if (x%i == 0) {
return false;
}
}
return true;
}
void judge() {
// 保证要我们要求的区间内
// 如果回文串的长度位于alen与blen之间,那么就代表已经是位于区间内了
if (len == alen && strcmp(str, astr) < 0) return ;
if (len == blen && strcmp(str, bstr) > 0) return ;
if (isPrime()) {
cout << str << endl;
}
}
// cur用来记录现在产生的是回文串的第几位
void makePalindromes(int cur) {
if (cur == len/2) {
if (len%2 == 0) { // 产生偶数长度的
str[len] = '\0';
judge();
} else { // 产生奇数长度的回文串,中间的那个位置可以为任意数字
for (int i = 0; i <= 9; ++i) {
str[cur] = i+'0';
str[len] = '\0';
judge();
}
}
return ;
}
if (cur == 0) { // 在规定了长度的情况下,首位不能为0
for (int i = 1; i <= 9; ++i) {
str[cur] = i+'0';
str[len-1-cur] = str[cur]; // 两端对称
makePalindromes(cur+1);
}
} else {
for (int i = 0; i <= 9; ++i) {
str[cur] = i+'0';
str[len-1-cur] = str[cur];
makePalindromes(cur+1);
}
}
}
int main() {
#ifdef MARK
freopen("pprime.in", "r", stdin);
freopen("pprime.out", "w", stdout);
#endif // MARK
while (~scanf("%s%s", astr, bstr)) {
alen = strlen(astr);
blen = strlen(bstr);
// 枚举所有可能长度的回文串
for (len = alen; len <= blen; ++len) {
makePalindromes(0);
}
}
return 0;
}
官方题解
官方总共给出了四种代码,但是我觉得前两种代码是比较好理解的。具体的思路在这里,其中第二种方法相对于第一种方法有一个很妙的剪枝。
官方代码1
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
FILE *fout;
long a, b;
int
isprime(long n)
{
long i;
if(n == 2)
return 1;
if(n%2 == 0)
return 0;
for(i=3; i*i <= n; i+=2)
if(n%i == 0)
return 0;
return 1;
}
void
gen(int i, int isodd)
{
char buf[30];
char *p, *q;
long n;
sprintf(buf, "%d", i);
p = buf+strlen(buf);
q = p - isodd;
while(q > buf)
*p++ = *--q;
*p = '\0';
n = atol(buf);
if(a <= n && n <= b && isprime(n))
fprintf(fout, "%ld\n", n);
}
void
genoddeven(int lo, int hi)
{
int i;
for(i=lo; i<=hi; i++)
gen(i, 1);
for(i=lo; i<=hi; i++)
gen(i, 0);
}
void
generate(void)
{
genoddeven(1, 9);
genoddeven(10, 99);
genoddeven(100, 999);
genoddeven(1000, 9999);
}
void
main(void)
{
FILE *fin;
fin = fopen("pprime.in", "r");
fout = fopen("pprime.out", "w");
assert(fin != NULL && fout != NULL);
fscanf(fin, "%ld %ld", &a, &b);
generate();
exit (0);
}
官方代码2
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
FILE *fout;
long a, b;
int
isprime(long n)
{
long i;
if(n == 2)
return 1;
if(n%2 == 0)
return 0;
for(i=3; i*i <= n; i+=2)
if(n%i == 0)
return 0;
return 1;
}
void
gen(int i)
{
char buf[30];
char *p, *q;
long n;
sprintf(buf, "%d", i);
p = buf+strlen(buf);
q = p - 1;
while(q > buf)
*p++ = *--q;
*p = '\0';
n = atol(buf);
if(a <= n && n <= b && isprime(n))
fprintf(fout, "%ld\n", n);
}
void
generate(void)
{
int i;
for (i = 1; i <= 9; i++)
gen(i);
if(a <= 11 && 11 <= b)
fprintf(fout, "11\n");
for (i = 10; i <= 9999; i++)
gen(i);
}
void
main(void)
{
FILE *fin;
fin = fopen("pprime.in", "r");
fout = fopen("pprime.out", "w");
assert(fin != NULL && fout != NULL);
fscanf(fin, "%ld %ld", &a, &b);
generate();
exit (0);
}
USACO Section 1.5 Prime Palindromes 解题报告的更多相关文章
- USACO Section 1.3 Prime Cryptarithm 解题报告
题目 题目描述 牛式的定义,我们首先需要看下面这个算式结构: * * * x * * ------- * * * <-- partial product 1 * * * <-- parti ...
- USACO Section 1.2 Dual Palindromes 解题报告
题目 题目描述 有一些数(如 21),在十进制时不是回文数,但在其它进制(如二进制时为 10101)时就是回文数. 编一个程序,从文件读入两个十进制数N.S.然后找出前 N 个满足大于 S 且在两种以 ...
- USACO Section1.5 Prime Palindromes 解题报告
pprime解题报告 —— icedream61 博客园(转载请注明出处)--------------------------------------------------------------- ...
- USACO Section 1.4 Arithmetic Progressions 解题报告
题目 题目描述 现在给你一个数集,里面的数字都是由p^2+q^2这种形式构成的0 <= p,q <= M,我现在需要你在其中找出一个长为N的等差数列,数列中的第一个数字为a,公差为b,当你 ...
- USACO Section 1.3 Combination Lock 解题报告
题目 题目描述 农夫John的牛从农场逃脱出去了,所以他决定用一个密码锁来把农场的门锁起来,这个密码锁有三个表盘,每个表盘都是环形的,而且上面刻有1~N,现在John设了一个开锁密码,而且这个锁的设计 ...
- USACO Section 1.3 Barn Repair 解题报告
题目 题目描述 某农夫有一个养牛场,所有的牛圈都相邻的排成一排(共有S个牛圈),每个牛圈里面最多只圈养一头牛.有一天狂风卷积着乌云,电闪雷鸣,把牛圈的门给刮走了.幸运的是,有些牛因为放假,所以没在自己 ...
- USACO Section 1.3 Mixing Milk 解题报告
题目 题目描述 Merry Milk Makers 公司的业务是销售牛奶.它从农夫那里收购N单位的牛奶,然后销售出去.现在有M个农夫,每个农夫都存有一定量的牛奶,而且每个农夫都会有自己的定价.假设所有 ...
- USACO Section 1.2 Palindromic Squares 解题报告
题目 题目描述 输入一个基数B,现在要从1到300之间找出一些符合要求的数字N.如果N的平方转换成B进制数之后是一个回文串,那么N就符合要求.我们将N转换成B进制数输出,然后再将N的平方转换成B进制数 ...
- USACO Section 1.2 Milking Cows 解题报告
题目 题目描述 有3个农夫每天早上五点钟便起床去挤牛奶,现在第一个农夫挤牛奶的时刻为300(五点钟之后的第300个分钟开始),1000的时候结束.第二个农夫从700开始,1200结束.最后一个农夫从1 ...
随机推荐
- Unity优化方向——优化Unity游戏中的图形渲染(译)
CPU bound:CPU性能边界,是指CPU计算时一直处于占用率很高的情况. GPU bound:GPU性能边界,同样的是指GPU计算时一直处于占用率很高的情况. 原文:https://unity3 ...
- 10分钟了解 pandas - pandas官方文档译文 [原创]
10 Minutes to pandas 英文原文:https://pandas.pydata.org/pandas-docs/stable/10min.html 版本:pandas 0.23.4 采 ...
- Netty源码分析第5章(ByteBuf)---->第3节: 缓冲区分配器
Netty源码分析第五章: ByteBuf 第三节: 缓冲区分配器 缓冲区分配器, 顾明思议就是分配缓冲区的工具, 在netty中, 缓冲区分配器的顶级抽象是接口ByteBufAllocator, 里 ...
- VMware两台虚拟机之间文件共享
虚拟机A的文件拷贝到虚拟机B scp[参数][原路径][目标路径] eg: scp -r root@192.168.0.172:/home/rookie/下载/ /home/rooookie/下载/ ...
- 基于WebSocket协议的性能测试
互联网应用时代,用户获取信息的方式从传统媒体到新媒体,信息时效性对通信技术要求越来越高, HTTP协议已经不能适用.于是WebSocket出现了,它实现浏览器与服务器的全双工通信,服务端主动向客户端发 ...
- 03_set slice的时间复杂度
set slice O(n+k) 使用切片赋值来解释set slice的时间复杂度 (1) 对li[0:3]赋值首先会删除1,2,3,空出来的位置被后面的元素依次向前移动填充,由del slice 得 ...
- [T-ARA/超新星][TTL (Time To Love)]
歌词来源:http://music.163.com/#/song?id=5403002 作曲 : 金道勋 [作曲 : 金道勋] 作词 : Rhymer/Joosuc/황성진 [作词 : Rhymer/ ...
- python 输出格式化之后的时间格式
import timetime.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
- cd命令详解
基础命令学习目录首页 cd 进入用户主目录: cd ~ 进入用户主目录: cd - 返回进入此目录之前所在的目录: cd .. 返回上级目录(若当前目录为“/“,则执行完后还在“/":&qu ...
- 关于手机端h5上传图片配合exif.min.js,processImg.js的使用
首先这里有个new FileReader()的概念,这是h5新增的,用来把文件读入内存,并且读取文件中的数据.FileReader接口提供了一个异步API,使用该API可以在浏览器主线程中异步访问文件 ...