ZZUOJ-1222- 属于ACMer的游戏 猜素数 (某月赛,总结一下素数筛选法)

题目位置:1222: 属于ACMer的游戏 猜素数

1222: 属于ACMer的游戏 猜素数

Time Limit: 1 Sec  Memory Limit: 128 MB

Submit: 88  Solved: 21

[Submit][Status][Web Board]

Description

ACM实验室的众大神们喜欢聚餐大家一起HAPPY 尤其卢学长喜欢请大家HAPPY,但是卢学长请吃饭有一个习惯,大家要一起玩一个热身游戏,猜素数.

游戏规则如下:

正常人的版本是这样:比如卢学长先约定一个数,并约定一个范围比如1~1000,然后大家开始猜范围内的数,逐渐缩小范围,比如唐学长是卢学长的下一个位置的人,然后唐学长猜了550,如果和卢学长约定的数一样则唐学长接受惩罚,否则缩小范围如果约定的数大于550则范围变成550~1000,否则变成1~550.同理挨个猜数,直到有人接受惩罚。

但是ACM实验室的众大神的版本作了一点点改进,即事先约定的数和后面猜的数必须是素数 这可难为了冷神,冷神不知道一共会有多少素数。所以只能拜托机智的众学弟学妹了。

输入两个数a,b(1<=a,b<=10^7)判断a,b范围内(包括a,b)会有多少素数呢?

数据不保证a小于b。

Input

a,b两个数(1<=a,b<=10^7)

Output

t 表示范围内有多少个素数

Sample Input

1 1015 202 300

Sample Output

4262

HINT

Source

geek eric

这里来总结一下素数筛选法。。(针对这题)

题意:很简单,就是去找两个数的之间的素数的个数(包括这两个数,且两个数的大小顺序不固定)

一般的线性筛法AC代码(Memory:40624   Time:640):

/*************************************************************************
	> File Name: a.cpp
	> Author: zzuspy
	> Mail: [email protected]
	> Created Time: 2014年12月01日 星期一 12时50分31秒
 ************************************************************************/

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;

const int maxn = 10000005;
int vis[maxn] = {1,1};

int main()
{
	int m = sqrt(maxn+0.5);
	for(int i = 2; i<=m; i++)
	if(!vis[i])
	{
		for(int j = i*i; j<=maxn; j+=i) vis[j] = 1;//筛法过程
	}
	int a, b;
	while(scanf("%d %d", &a, &b)!=EOF)
	{
		int ans = 0;
		int t = max(a,b);
		a=min(a,b);
		b=t;
		for(int i=a; i<=b; i++)
		{
			if(!vis[i])ans++;
		}
		printf("%d\n", ans);
	}
	return 0;
}

更快的线性筛法AC代码(Memory:21092  Time:296)(时间是省了一半多,但是却复杂了一倍多,按情况选择更好的方法吧):

/*************************************************************************
	> File Name: b.cpp
	> Author: zzuspy
	> Mail: [email protected]
	> Created Time: 2014年12月01日 星期一 13时44分39秒
 ************************************************************************/

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;

const int maxn = 10000005/2;
int vis[maxn];

int main()
{
	int m = (int) sqrt(maxn);
	for(int i = 0; i<m; i++)
	if(!vis[i])//如果 i+i+3 是素数
	{
		for(int k=i+i+3, j=k*i+k+i; j<maxn; j+=k)
		{//这里只筛选奇数
	         // 筛法起点是 p[i]所对应素数的平方 k^2                                        
                // k^2在 p 中的位置是 k*i+k+i
                //    下标 i         k*i+k+i
                //对应数值 k=i+i+3   k^2    

                       vis[j] = 1;
		}
	}
	int a, b;
	while(scanf("%d %d", &a, &b)!=EOF)
	{
		int t = max(a,b), ans=0;
		a=min(a,b); b=t;
		if(a<=2)
		{
			ans++;
			a=2;
		}
		if(b>=3 && b-a>=1)
		for(int i=a/2-1; i<=(b-3)/2; i++)
		{
			if(!vis[i])ans++;
		}
		else if(b==a && a%2==1 && !vis[(a-3)/2])ans++;
		printf("%d\n", ans);
	}
	return 0;
}
//素数都存放在 p 数组中,p[i]=true代表 i+i+2 是素数。
//举例,3是素数,按3*3,3*5,3*7...的次序筛选,因为只保存奇数,所以不用删3*4,3*6....

时间: 2024-11-03 20:51:53

ZZUOJ-1222- 属于ACMer的游戏 猜素数 (某月赛,总结一下素数筛选法)的相关文章

python写的第一个简单小游戏-猜数字

1 #Filename:game1.py 2 3 guess=10 4 running=True 5 while running: 6 try: 7 answer=int(raw_input('Guess what i think:')) 8 except: 9 print 'Please input interga\n' 10 continue 11 12 if answer<guess: 13 print 'Your answer is too small\n' 14 continue 15

CASIO 5800P计算器游戏--猜数字游戏

CASIO 5800P 计算器游戏--猜数字游戏原代码 我编的计算器小游戏--猜数字游戏 LbI I "xxGUESS NUMBERxx xPROGRAMMER:JCHx ---------------- START>>>>>>>[EXE]"◢ LbI Q "xxxDIFFICULTYxxx [1EASY] [2MIDDLE] [3HARD]"?→N: N=1=>GOTO N:N=2=>GOTO O: N=3=&

筛选法求素数

筛选法求素数,不断的用3,5,7,等素数作为筛子,筛除这些数的倍数,即将合数筛除.用辅助数组p记录数i是否是素数. vector<int> prime(int n) { vector<int> p(n+1); for(int i=2;i<=n;i+=2) { if(i%2==0&&i>2) p[i]=0; else p[i]=1; } for(int i=3;i<=(int)(sqrt((double)n));i+=2) { if(p[i]) fo

素数筛选法

筛选法(埃拉托色尼(Eratosthenes)筛法)求素数,例如1~100 思想:逐个筛选,直到int(sqrt(100))个 1)因为1不是质数,将1筛去 2)2是质数,将2的倍数全都挖掉 3)3是质数,将3的倍数全都挖掉 4)4已经被挖去,不进行与4相关的操作 5)5是质数,将5的倍数全都挖掉 6)这个过程一直进行到后面的数全都挖掉为止 不是从1开始:如10~18----一个一个筛--->18 #include <stdio.h> #include <math.h> #i

hdu 5407 CRB and Candies(素数筛选法,除法取模(乘法逆元))

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5407 解题思路: 官方题解: The problem is just to calculate g(N) =\ LCM(C(N,0), C(N,1), ..., C(N, N))g(N) = LCM(C(N,0),C(N,1),...,C(N,N)). Introducing function f(n) =\ LCM(1, 2, ..., n)f(n) = LCM(1,2,...,n), the

判断101-200之间有多少个素数,并输出所有素数(C)

/* *题目:判断101-200之间有多少个素数,并输出所有素数. * *程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果 *能被整除,则表明此数不是素数,反之是素数. */ #include<stdio.h> #include<math.h> int main() { int k,i,j,m,sum=0; int flag; for(i=101;i<=200;i++){ flag=1; k=sqrt(i); for(j=2;j<=k;j++){

数组拷贝、数组函数、通过数组函数来模拟数据结构的栈和队列、回调的意义、数组函数的排序问题、算法以及寻找素数的筛选法

1.数组的拷贝数组拷贝时指针的指向问题. 数组在拷贝时,指针的位置随之复制[这一点拷贝是完全一样]但是如果拷贝的数组的指针是非法的,那么拷贝出新指针的位置进行初始化<?php$arr1=array('123');end($arr1);next($arr1);//这个指针非法$arr2 = $arr1;//这里进行数组的拷贝var_dump(current($arr2));//得到指向‘123’元素的指针var_dump(current($arr1));//此时这个数组的指针有问题?> 但是拷贝

判断101-200之间有多少个素数,并输出所有素数。

package com.mumu.ready;import static com.mumu.ready.Print.print; public class Prime {//题目:判断101-200之间有多少个素数,并输出所有素数. public static boolean prime(int n) { boolean flag=false; for(int i=2;i<=n/2;i++) { if(n%i==0) { flag=true; continue; } } return flag;

HDU 2161 Primes (素数筛选法)

题意:输入一个数判断是不是素数,并规定2不是素数. 析:一看就很简单吧,用素数筛选法,注意的是结束条件是n<0,一开始被坑了... 不说了,直接上代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> using namespace std; typedef long long LL; const int maxn = 16000 + 10; int p