版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Nicht_sehen/article/details/84179221
问题描述
long_xiao和const_hhh是一对恩爱的夫妻。
他们在京城经营着一家中药店,夫妻二人医术精湛、古道热肠,虽然年过花甲,身体依然硬朗。更重要的是,他们的思维仍然十分活跃,不仅了解大家的要求,还能给他们许多惊喜。
除了治病救人,他们的中药配方还有舒筋活络,排毒养颜的功效。正因为如此,中药店门庭若市,甚至有人不远千里,慕名而来。
药店里药材种类繁多,组成的配方也就非常多。为了提高服务质量,店里的伙计灰来灰去将药材和配方进行编号,灰来灰去可以通过配方的编号快速找到所需药材的编号。
一天,店里的伙计灰来灰去提议可以借此机会来向大家普及一下数学知识,夫妻二人表示赞成,决定每周一在店门口的公告栏中发布新的知识点。
这周一他们提供了一个简单但是有趣的知识点:
“素数:一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做素数“。
到了周末,灰来灰去为了检验大家对知识点的掌握情况,使得今天的配方都由三种药材组成,所需的三种药材的编号都为素数,且加起来等于配方的编号。因为会有多种情况出现,灰来灰去使得三个素数的乘积最大。
现在,药店会给你开出一剂配方,编号为n。如果你能把他拆成3个素数的和或者告诉灰来灰去无法拆成3个素数的和,那么灰来灰去就可以快速找到药材,并免费赠送你一副他们的镇店配方。
输入描述
输入第一行包含一个正整数T,代表有T次配方的询问。
对于每组数据,输入包含一个正整数n(1<=n<=10000),代表配方的编号。
输出描述
对于每组数据,如果n不能写成三个素数的和,输出-1。
否则在一行从小到大输出三个素数以及最大乘积。
样例输入
2
20
3
样例输出
2 7 11 154
-1
看到这个题的第一反应就是要打表,这里说一下几种素数打表的方法
- 普通方法
时间复杂度为O(n^2)
void prime(int n)
{
for (int i = 2; i < n; i++)
{
int j;
for (j = 2; j <= i; j++)
{
if (i%j==0) break;
}
}
}
- 普通方法改进——循环到sqrt(n)
时间复杂度为O(n*sqrt(n))
void prime(int n)
{
for (int i = 2; i < n; ++i)
{
int j;
for (j = 2; j <= sqrt(i); ++j)
{
if (i%j==0) break;
}
}
}
- 普通筛表——埃拉托斯特尼筛法
所使用的原理是从2开始,将每个素数的各个倍数,标记成合数。一个素数的各个倍数,是一个差为此素数本身的等差数列。此为这个筛法和试除法不同的关键之处,后者是以素数来测试每个待测数能否被整除。时间复杂度为O(n log log n)
void isprime(int n, int prime[])
{
int i;
for(i = 0; i <= n; i++)
prime[i] = i;
int j;
for(j = 2; j < sqrt(n); j++)
{
int k;
for(k = j + 1; k <= n; k++)
{
if(prime[k] != 0 && prime[k] % j == 0)
prime[k] = 0;
}
}
}
- 线性筛表——欧拉筛表
时间复杂度降低到O(n)
void isprime()
{
memset(visit, true, sizeof(visit));
int num = 0;
for (int i = 2; i <= n; ++i)
{
if (visit[i] == true)
{
num++;
prime[num] = i;
}
for (int j = 1; ((j <= num) && (i * prime[j] <= n)); ++j)
{
visit[i * prime[j]] = false;
if (i % prime[j] == 0) break;
}
}
}
本题代码:
#include<stdio.h>
#include<math.h>
#include<string.h>
#define min(a,b)(a<b?a:b)
#define max(a,b)(a>b?a:b)
int prime[10000];
int num;
bool visit[10000];
void pr()
{
memset(visit, true, sizeof(visit));
num = 0;
for (int i = 2; i <= 10000; ++i)
{
if (visit[i] == true)
{
num++;
prime[num] = i;
}
for (int j = 1; ((j <= num) && (i * prime[j] <= 10000)); ++j)
{
visit[i * prime[j]] = false;
if (i % prime[j] == 0) break;
}
}
}
int main()
{
pr();
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
long long int Max=-1,m;
int x,y,z,k;
for(int i=0;i<num;i++)
{
for(int j = 0 ; j<num ; j++)
{
int k = n-prime[i]-prime[j];
if(k >=0 && visit[k])
{
m=(long long int)prime[i]*prime[j]*k;
if((m > Max)&&m)
{
Max = m;
x = min(prime[i] , min(prime[j] , k));
z = max(prime[i] , max(prime[j] , k));
y = n-x-z;
}
}
}
}
if(Max == -1)
printf("-1\n");
else
printf("%d %d %d %lld\n",x,y,z,Max);
}
return 0;
}