洛谷P1218 [USACO1.5]特殊的质数肋骨 Superprime Rib
水题一道……
题目描述
农民约翰的母牛总是产生最好的肋骨。你能通过农民约翰和美国农业部标记在每根肋骨上的数字认出它们。农民约翰确定他卖给买方的是真正的质数肋骨,是因为从右边开始切下肋骨,每次还剩下的肋骨上的数字都组成一个质数,举例来说: 7 3 3 1 全部肋骨上的数字 7331是质数;三根肋骨 733是质数;二根肋骨 73 是质数;当然,最后一根肋骨 7 也是质数。 7331 被叫做长度 4 的特殊质数。写一个程序对给定的肋骨的数目 N (1<=N<=8),求出所有的特殊质数。数字1不被看作一个质数。
输入格式
单独的一行包含N。
输出格式
按顺序输出长度为 N 的特殊质数,每行一个。
输入输出样例
输入 #1
4
输出 #1
2333 2339 2393 2399 2939 3119 3137 3733 3739 3793 3797 5939 7193 7331 7333 7393
说明/提示
题目翻译来自NOCOW。
USACO Training Section 1.5
Solution
Algorithm1
可以枚举10n-1~10n之间所有的数,再依次把这个数除以10,判断其是否为质数。
一旦不是就跳出循环。O(n)
Code1
1 #include<iostream>//不想OI一场空,千万别用万能头 2 #include<algorithm>//快排sort() 3 #include<cstdio>//能不用cin就不用 4 #include<cstring> 5 #include<cmath> 6 #include<map> 7 #include<vector> 8 #include<queue> 9 #define IL inline 10 using namespace std; 11 int n; 12 bool flag; 13 IL bool prime(int num) 14 { 15 if(num<=1) return 0; 16 for(int i=2;i<=sqrt(num);i++) 17 if(num%i==0) return 0; 18 return 1; 19 } 20 int main() 21 { 22 cin>>n; 23 for(int i=pow(10,n-1);i<pow(10,n);i++) 24 { 25 flag=1; 26 for(int j=i;j>0;j/=10) 27 if(!prime(j)){ 28 flag=0; 29 break; 30 } 31 if(flag) cout<<i<<endl; 32 } 33 34 return 0; 35 }
Algorithm2
事实证明,在$n = 6$时,计算速度太慢了。于是我想到了可以把prime表先打出来。
为了节省空间,使用bool型数组table。table[i]表示i是否为质数。
Code2
1 //504…… 2 //若需查看,请复制下面的链接 3 https://files-cdn.cnblogs.com/files/send-off-a-friend/%E6%B4%9B%E8%B0%B7P1218%E6%89%93%E8%A1%A8%E7%A8%8B%E5%BA%8F%E5%92%8C%E6%8F%90%E4%BA%A4%E7%A8%8B%E5%BA%8F%E4%B8%8E%E6%BA%90%E4%BB%A3%E7%A0%81.rar
Algorithm3
但是数组的空间的有限的,没法开那么大的数组。
考虑使用map<int,bool>table
这样就可以多存一点了
STL大法好……
Code3
这里就不给出代码了,因为没有很大的意义。
如需代码请在下方评论
好吧……我还是上传了
(使用了记忆化)
1 #include<iostream>//不想OI一场空,千万别用万能头 2 #include<algorithm>//快排sort() 3 #include<cstdio>//能不用cin就不用 4 #include<cstring> 5 #include<cmath> 6 #include<map> 7 #include<vector> 8 #include<queue> 9 #define IL inline 10 using namespace std; 11 int n; 12 bool flag; 13 map<int,bool>table,vis; 14 IL bool prime(int num) 15 { 16 if(num<=1) return 0; 17 if(vis[num]) return table[num]; 18 vis[num]=1; 19 for(int i=2;i<=sqrt(num);i++) 20 if(num%i==0) return table[num]=0; 21 return table[num]=1; 22 } 23 int main() 24 { 25 cin>>n; 26 for(int i=pow(10,n-1);i<pow(10,n);i++) 27 { 28 flag=1; 29 for(int j=i;j>0;j/=10) 30 if(!prime(j)){ 31 flag=0; 32 break; 33 } 34 if(flag) cout<<i<<endl; 35 } 36 return 0; 37 }
Algorithm4
类似于枚举每一位数的想法
使用dfs决定某一位数能放什么。
从0位开始,到n位时输出答案。
Code4
1 #include<iostream>//不想OI一场空,千万别用万能头 2 #include<algorithm>//快排sort() 3 #include<cstdio>//能不用cin就不用 4 #include<cstring> 5 #include<cmath> 6 #include<map> 7 #include<vector> 8 #include<queue> 9 #define IL inline 10 using namespace std; 11 int n; 12 bool flag; 13 IL bool prime(int num) 14 { 15 if(num<=1) return 0; 16 for(int i=2;i<=sqrt(num);i++) 17 if(num%i==0) return 0; 18 return 1; 19 } 20 IL void dfs(int depth,int num) 21 { 22 if(depth==n){ 23 cout<<num<<endl; 24 return; 25 } 26 num*=10; 27 for(int i=0;i<=9;i++) 28 if(prime(num+i)) 29 dfs(depth+1,num+i); 30 } 31 int main() 32 { 33 cin>>n; 34 dfs(0,0); 35 return 0; 36 }
Attention
无……
水题一道……