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时,二者时间貌似差不多...
该题用这两种打表方法都可以