【HDU/POJ/ZOJ】Calling Extraterrestrial Intelligence Again (素数打表模板)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/CSDN___CSDN/article/details/87270412

http://poj.org/problem?id=1411  POJ

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1689  ZOJ

http://acm.hdu.edu.cn/showproblem.php?pid=1239  HDU

都是同一个题,但是可能你在HDU上AC,在POJ和ZOJ上是TLE(所以还有待改进)

【题目大意】In other words, you will receive an integer m and a fraction a / b. It holds that m > 4 and 0 < a / b < 1. You should find the pair of prime numbers p, q such that pq <= m and a / b <= p / q <= 1, and furthermore, the product pq takes the maximum value among such pairs of two prime numbers. You should report p and q as the "most suitable" width and height of the translated picture.

 You may assume 4 < m <= 100000 and 1 <= a <= b <= 1000

素数打表 + 遍历 + 剪枝

【注意】

prime数组里需要存放素数的最大值是多少,存的过多也会TLE。

考虑如果q是大于10000的某一个数,p是另一个质数

如果p<10,那么p/q<=0.001

如果p>10,那么pq>100000,

因为这是题目中所给条件,1 <= a <= b <= 1000,所以min(a/b)=0.001,同时要求pq <= 100000 ,所以表里的最大质数不会超过10000。

HDUAC

#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

bool  vis[10000];
int prime[2000];
int num = 0;
void table()
{
	int i,j;
	memset(prime,0,sizeof(prime));
	memset(vis,true,sizeof(vis));
	for(i=2;i<10000;i++)
	{
		if(vis[i])
		{
			prime[num++] = i;
		}
		for(j=0;(j<num && i*prime[j]<10000);j++)
		{
			vis[i*prime[j]] = false;
			if(i%prime[j]==0)	break;
		}
	}
}

int main ()
{
	table();
	int n,i,j;
	double a,b;
//	cout << prime[num-1] << endl;
	while(scanf("%d%lf%lf",&n,&a,&b)!=EOF)
	{
		if(n==0 && a==0 && b==0)
			break;
		double lim = a/b;
		int maxn = 0; 
		int a1,a2;
		for(i=num-1;i>=0;i--)
		{
			for(j=i;j>=0;j--)
			{
				if(prime[i]>n || prime[j]>n || prime[i]*prime[j]>n || 1.0*prime[j]/prime[i]<lim)
					continue;
				if(prime[i]*prime[j]>maxn)
				{
					maxn = prime[i]*prime[j];
					a1 = prime[i];
					a2 = prime[j];
				}
			}
		} 
		if(a1 > a2)
		{
			int t = a1;
			a1 = a2;
			a2 = t;
		}
		cout << a1 << " " << a2 << endl;
	}
	return 0;
} 

ALL_AC 

#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int N = 10000;
bool  vis[10000];
int prime[2000];
int num = 0;

void table()
{
	int i,j;
	memset(prime,0,sizeof(prime));
	memset(vis,true,sizeof(vis));
	for(i=2;i<10000;i++)
	{
		if(vis[i])
		{
			prime[num++] = i;
		}
		for(j=0;(j<num && i*prime[j]<10000);j++)
		{
			vis[i*prime[j]] = false;
			if(i%prime[j]==0)	break;
		}
	}
}

int main ()
{
	table();
	int n,i,j;
	int a,b;

	while(scanf("%d%d%d",&n,&a,&b)!=EOF)
	{
		if(n==0 && a==0 && b==0)
			break;
		double lim = 1.0*a/b;
		int maxn = 0; 
		int a1,a2;
		for(i=num-1;i>=0;i--)
		{
			if(prime[i]>n)
				continue;
			for(j=i;j<=num-1;j++)//j是比i大的素数 
			{
				int t = prime[i]*prime[j];
				if (prime[j]>n || t>n || 1.0*prime[i]/prime[j]<lim)
					break;
				if(t>maxn)
				{
					maxn = t;
					a1 = prime[i];
					a2 = prime[j];
				}
			}
		} 
		cout << a1 << " " << a2 << endl;
	}
	return 0;
} 
#include<iostream>
#include<cstring>
#include<cstdio>
#include<ctime>
#include<algorithm>
using namespace std;
#define M 1000000
bool visit[10100000];
int prime[10000000];
 
 
void table1()
{
	memset(visit,true,sizeof(visit));
	int num = 0;
	for (int i = 2; i <= M; ++i)
	{
		if (visit[i] == true)
		{
			num++;
			prime[num] = i;
		}
		for (int j = 1; ((j <= num) && (i * prime[j] <= M));  ++j)
		{
			visit[i * prime[j]] = false;
			if (i % prime[j] == 0) break; //点睛之笔
		}
	}
}

void table2()
{
	memset(visit,true,sizeof(visit));
	int num = 0;
	for (int i = 2; i <= M; ++i)
	{
		if(visit[i])
		{
			prime[num++] = i;
			for(int j=i+i;j<M;j+=i)
			{
				visit[j] = false;
			}
		}
	}	
}


int main()
{
	clock_t start, finish; 
	double Total_time;
	memset(prime, 0, sizeof(prime));
	int count = 0;
	start = clock();//开始时间 
	table2();
	finish = clock();
	Total_time = (double)(finish - start) / CLOCKS_PER_SEC; 
	cout << "素数打表耗时:" << Total_time << endl; 
	for(int i = 0; i <= M; ++i)
	{
		if(prime[i])
		{
			count++;
		}	
	} 	
	cout<< "在" << M << "个数中,素数个数为:"<< count << endl;	
}

在M=1000000时,二者时间貌似差不多...

该题用这两种打表方法都可以

猜你喜欢

转载自blog.csdn.net/CSDN___CSDN/article/details/87270412