题解 P1218 【[USACO1.5]特殊的质数肋骨 Superprime Rib】

ShineEternal

2019-07-04 10:40:35

Solution

# 前言: 简单看了一下其他题解,发现思路~~貌似~~比较独特,没有重复,于是来分析一下。 --- # 分析: 我们首先想到,如果穷举n位的所有数字可能会超时,便不妨设想已经枚举出来,然后观察一下规律。 由题目可以很容易的得出,n位数的特殊质数中最高位一定是质数~~废话~~ 这样一位的质数就简单了:2,3,5,7 那么倒推回去,一定只有这些数字开头。 瞬间就爽了很多。 然后再考虑后面的数位。 这时就不能片面的判断单独一位能否影响整个数字了。但我们至少可以得出结论,肋骨一定**不在**以2,4,5,6,8里。 换句话说就可能在1,3,7,9中。 于是一位一位算就行。 我用了两个数组来回倒腾。 **代码长度适中,但仔细一看就会发现很好写** > code: ```cpp #include<cstdio> #include<cmath> using namespace std; int ex[5]={0,1,3,7,9},a[100005],b[100005]; bool pd(int x) { for(int i=2;i<=sqrt(x);i++) { if(x%i==0)return 0; } return 1; } int main() { int n; scanf("%d",&n); a[1]=2; a[2]=3; a[3]=5; a[4]=7; int cnt=4; int flag=0; int sum=0; n--; while(n--) { if(flag==0) { sum=0; for(int i=1;i<=cnt;i++) { for(int j=1;j<=4;j++) { b[++sum]=a[i]*10+ex[j]; if(!pd(b[sum])) { b[sum--]=0; } } } } else { cnt=0; for(int i=1;i<=sum;i++) { for(int j=1;j<=4;j++) { a[++cnt]=b[i]*10+ex[j]; if(!pd(a[cnt])) { a[cnt--]=0; } } } } flag=(flag+1)%2; } if(flag==0) { for(int i=1;i<=cnt;i++) { printf("%d\n",a[i]); } } else { for(int i=1;i<=sum;i++) { printf("%d\n",b[i]); } } return 0; } ```