您的位置:首页 > 其它

USACO Prime Palindroms

2015-02-24 14:11 239 查看
【题意】

给定a,b,求所有p满足p属于[a,b]且p为素数且p为回文数(5<=a,b<=10000000)

【解析】

USACO上评测时可以使用的空间真的不大啊,开到10000000就会爆掉。

还有应该每道题的时间限制都是1s,因为本题超过就算没通过了。

这道题要求三个条件,那就要分层次处理。

[ 方法1 ]

枚举a到b的所有数进行判断。

因为USACO的空间限制,所以素数判定只能用O(n 根号n)的。

很明显会爆时间,但还是附两个代码。

试除法:

/*
ID:y2007031
PROG:pprime
LANG:C++
*/

#include <cstdio>
#include <cstring>
#include <cstdlib>

using namespace std;

const int N=10000001;

int v
,p[N>>3];
int a,b;
int s[20];

int can(int i)
{
s[0]=0;
for (;i;i/=10) s[++s[0]]=i%10;
for (int i=1;i<=s[0]>>1;i++) if (s[i]^s[s[0]+1-i]) return 0;
return 1;
}


欧拉筛法:

int main(void)
{
freopen("pprime.in","r",stdin);
freopen("pprime.out","w",stdout);

scanf("%d%d",&a,&b);

v[1]=1;
for (int i=2;i<=b;i++)
{
if (!v[i]) p[++p[0]]=i;
for (int j=1;j<=p[0];j++)
{
if (i*p[j]>b) break;
v[i*p[j]]=1;
if (i%p[j]==0) break;
}
}

for (int i=1;i<=p[0];i++)
{
if (p[i]<a) continue;
if (p[i]>b) break;
if (a<=p[i]&&p[i]<=b&&can(p[i])) printf("%d\n",p[i]);
}

return 0;
}


[ 方法2 ]

不难发现回文串比素数少,而且知道第i位就可以知道n+1-i位(1个对应位)

所以可以先求出a,b的位数,然后枚举位数,进行b的位数-a的位数+1次搜索,找到所有回文串进行判定。

这里还要预先保存一下mtp
,就是十进制每位的位值。

最后检验的时候,一要判定满足在a到b间,二要判定是素数。

代码如下(正解):

/*
ID:y2007031
PROG:pprime
LANG:C++
*/

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>

using namespace std;

int a,b,la,lb;
int s[40];
int f[40],mtp[40];

void due(int k)
{
s[0]=0;
for (;k;k/=10) s[++s[0]]=k%10;
}

int check(int k)
{
if (k<=1) return 0;
for (int i=2;i<=(int)sqrt(k);i++) if (k%i==0) return 0;
return 1;
}

void DFS(int dep,int lmt,int now)
{
if (dep==(lmt>>1)+1)
{
if (lmt&1)
for (int i=0;i<=9;i++)
{
int t=now+i*mtp[dep];
if (a<=t&&t<=b&&check(now+i*mtp[dep]))
printf("%d\n",now+i*mtp[dep]);
}
else
if (a<=now&&now<=b&&check(now)) printf("%d\n",now);
return;
}
for (int i=0;i<=9;i++)
{
if (dep==1&&!i) continue;
DFS(dep+1,lmt,now+i*mtp[dep]+i*mtp[lmt-dep+1]);
}
}

int main(void)
{
freopen("pprime.in","r",stdin);
freopen("pprime.out","w",stdout);

scanf("%d%d",&a,&b);
due(a),la=s[0];
due(b),lb=s[0];

mtp[1]=1;
for (int i=2;i<=lb;i++) mtp[i]=mtp[i-1]*10;
for (int i=la;i<=lb;i++) DFS(1,i,0);

return 0;
}


【总结】找到所有满足的数的问题,若有多个限制条件,要么可以想出一种方法直接解决,要么就分层次处理,找到一种时间复杂度最低的就是正解。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: