USACO1.5Superprime Rid[附带关于素数算法时间测试]

题目描述

农民约翰的母牛总是产生最好的肋骨。你能通过农民约翰和美国农业部标记在每根肋骨上的数字认出它们。农民约翰确定他卖给买方的是真正的质数肋骨,是因为从右边开始切下肋骨,每次还剩下的肋骨上的数字都组成一个质数,举例来说: 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

-----------------------------

第一位一定是2,3,5,7 ,以后各位只能是单数,并且不能是5,直接dfs每一位,只要不是prime就退出

用哪个方法判素数呢?

一开始随手打了欧拉筛法,结果MLE+TLE,又改了个朴素算法,结果AC了....

对于n等于8,其实只有4^8=65536次检测,太少了,即使根号n的复杂度,合起来是16777216,欧拉筛法却要10^8

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

于是我开始测速玩,环境MBA,n=1e8,我实现的Euler筛法要跑1.3s左右,Eratosthenes筛法要近3s......然而,朴素竟是1.1s,Miller-Rabin只要0.5s;

Miller-Rabin完虐Euler筛法暂且不说,为什么朴素方法也比Euler筛法快,O(n根号n)与O(n)没法比吧..........这是玄学

吓得我又测一次,n=1e6,Eratosthenes筛法0.5s,Euler筛法0.016s,朴素也在0.016s左右,Miller-Rabin只要0.1s

这是要Eratosthenes筛法情何以堪

------------------------------------------------------------------------------------------------------------------------------------------------------------

[2016-08-19更新]:都是memset惹的祸,Eratosthenes n=1e8可以2.26s,n=1e6可以0.021s,朴素也是0.021,然而Euler筛法却0.026s

            还是玄学

//
//  main.cpp
//  usaco1.5 superprime rib
//
//  Created by abc on 16/8/15.
//  Copyright © 2016年 abc. All rights reserved.
//

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int N=1e8+5,L=10;

int n=1,l;
//bool flag[N];int prime[N];
int st[4]={2,3,5,7},odd[4]={1,3,7,9},a[L];
//int es(int n){
//    int cp=0;
//    for(int i=2;i<=n;i++){
//        if(!flag[i]) prime[++cp]=i;
//        for(int j=1;j<=cp&&prime[j]*i<=n;j++){
//            flag[i*prime[j]]=1;
//            if(i%prime[j]==0) break;
//        }
//    }
//    return cp;
//}
inline int flag(int n){
    int m=sqrt(n)+1;
    for(int i=2;i<=m;i++) if(n%i==0) return 1;
    return 0;
}
void dfs(int now,int v){//cout<<now<<"\n";
    if(now==l+1){
        for(int i=1;i<=l;i++) printf("%d",a[i]);
        printf("\n");
        return;
    }
    for(int i=0;i<4;i++){
        a[now]=odd[i];
        if(flag(v*10+a[now])==0) dfs(now+1,v*10+a[now]);
    }
}
int main(int argc, const char * argv[]) {
    cin>>l;
    for(int i=1;i<=l;i++) n=10*n;
    //es(n);
    for(int i=0;i<4;i++){
        memset(a,0,sizeof(a));
        a[1]=st[i];
        dfs(2,st[i]);
    }
    return 0;
}
时间: 2024-10-06 20:58:46

USACO1.5Superprime Rid[附带关于素数算法时间测试]的相关文章

算法时间测试

1 //算法时间测试 基准法(定量分析) 大O法(定性分析) 2 //以下是基准法 3 #include "iostream" 4 #include "cstdio" 5 #include "ctime" 6 #include "windows.h" 7 using namespace std; 8 int main() 9 { 10 //法一 11 clock_t start1,end1;//clock_t 需头文件#inc

素数算法的优化之路

一.素数的定义 质数又称素数.指在一个大于1的自然数中,除了1和此整数自身外,不能被其他自然数(不包括0)整除的数.因为合数是由若干个质数相乘而得来的,所以,没有质数就没有合数,由此可见质数在数论中有着很重要的地位. 比如:2,3,5,7,9.....都是素数. 二.构造素数算法 写算法之前,先来说说以下这个东西: 对于任意一个合数n,如果它有两个质因子x,y,显然n = x*y, 所以,由不等式性质可得,x <= sqrt(n), 即 x <= n^(1/2). 推广一下,对于任意一个合数,

试探究一种查找素数算法

解题思路:构造链表,使用筛除法 例如:求10以内素数 链表初始化:2 3 4 5 6 7 8 9 10 进行第一轮筛选后:2 3 5 7 9 也就是用2后面的数去除2, 第二轮筛选后:2 3 5 7 也就是用3后面的数去除3, 第三轮筛选后:2 3 5 7 也就是用5后面的数去除5 第四轮筛选后:2 3 5 7 代码: #include <stdio.h> #include <stdlib.h> #define N 1e5 // over this it is so slowly

数论部分第一节:素数与素性测试【详解】

数论部分第一节:素数与素性测试 一个数是素数(也叫质数),当且仅当它的约数只有两个——1和它本身.规定这两个约数不能相同,因此1不是素数.对素数的研究属于数论范畴,你可以看到许多数学家没事就想出一些符合某种性质的素数并称它为某某某素数.整个数论几乎就围绕着整除和素数之类的词转过去转过来.对于写代码的人来说,素数比想像中的更重要,Google一下BigPrime或者big_prime你总会发现大堆大堆用到了素数常量的程序代码.平时没事时可以记一些素数下来以备急用.我会选一些好记的素数,比如4567

机器学习算法:补一个k-近邻算法的测试

之前写k-近邻算法(http://boytnt.blog.51cto.com/966121/1569629)的时候,没附上测试数据,这回找了一个,测试一下算法的效果.数据来源于http://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data,关于乳腺癌的样本,属性描述见breast-cancer-wisconsin.names. 样本的大致形式

记一次筛素数算法的优化

求出1..n中有多少个素数的算法我们通常用筛数法,一种比较简单的实现如下: 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(const int argc, const char *argv[], const char *envp[]) 5 { 6 int64_t n; 7 int64_t i, j; 8 int64_t *arr; 9 int64_t cnt = 0; 10 11 if (argc != 2) { 12

【Miller-Rabin随机判素数算法】

实用性介绍:████████████████████████████████ 科学性证明:████████████████████████████████ ·在运算中尝试使用quick-pow和quick-mul加速.但实际告诉我们,在多次判素数的情况下,使用quick-mul反而会减速,原因可能是原装%运算消耗了大量时间.(复判重复数T取在4以上,不然很危险) ·大米饼目前只能将它作为"黑盒代码". 1 #include<bits/stdc++.h> 2 #define

几种简单的求素数算法的复杂度分析

素数的算法有很多种,现在主要讲两种算法及其改进版本的复杂度分析,解释性能提升的幅度.现以求100000内素数为例,两种算法分别是: 1.基础思路是去掉偶数,包括取模的范围,代码如下: print(2) for i in range(3,100000,2): for a in range(3,int(i*0.5)+1,2): if i%a == 0: break else: print(i,end = ' ')此两层循环的算法的复杂度为0.5n((n**0.5+1)/2) 2.应用一个素数定理:大

Java数据结构之算法时间度

1.度量一个程序(算法)执行时间的两种方法 1)事后统计的方法 这种方法可行, 但是有两个问题:一是要想对设计的算法的运行性能进行评测,需要实际运行该程序:二是所得时间的统计量依赖于计算机的硬件.软件等环境因素, 这种方式,要在同一台计算机的相同状态下运行,才能比较那个算法速度更快. 2)事前估算的方法 通过分析某个算法的时间复杂度来判断哪个算法更优. 2.时间频度 基本介绍:一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多.一个算法中的语句执行次数称为