USACO-Superprime Rib
http://ace.delos.com/usacoprob2?a=0ypAbo0pjhC&S=sprime
我的想法很简单,就是先生成一位数的素数,在这基础上生成二位,然后再生成三位四位。。。
有一个很简单但是很实用的优化,注意到,素数的各位必定是1,3,7,9,当然一位的素数2,3,5,7,另当别论。
这样,我们只需在前一位的基础上添上1,3,7,9,然后逐个判断是否为素数。很简单,但是效率很高。
百度上有人用DFS,不过生成方法基本类似。有人先求出所有素数再拆开来判断,都可以。nocow上展示的一个用DP写的程序,真是大神了。。。
#include <iostream> #include <cstdio> #include <math.h> using namespace std; int n; int f[10][10000]={0}; const int d[4]={1,3,7,9}; bool check(int x) //判断x是否为素数 { int xx=int(sqrt(x)); for (int i=2;i<=xx;i++) if (x%i==0) return 0; return true; } int main() { freopen("sprime.in","r",stdin); freopen("sprime.out","w",stdout); cin>>n; f[1][0]=4; f[1][1]=2; f[1][2]=3; f[1][3]=5; f[1][4]=7; int temp; for (int i=2;i<=n;i++) for (int j=1;j<=f[i-1][0];j++) for (int k=0;k<4;k++) { temp=f[i-1][j]*10+d[k]; if (check(temp)) f[i][++f[i][0]]=temp; } for (int i=1;i<=f[n][0];i++) cout<<f[n][i]<<endl; return 0; }
我发现USACO的first time好像这么容易拿的呢?