NOJ 2096
题目描述
赵信——德玛西亚的总管,可谓一人之下,万人之上。但谁能想到,他以前在诺克萨斯的角斗场过的是怎样的生活?
那时,成千上万的奴隶或战俘被抓进角斗场,通过血腥的杀戮供贵族们取乐。所以,为了活下去,除了自身的实力之外,拉帮结派也是必不可少的。显然,这样的事只可能发生在互相信赖的人的中间,而在当时,人们互相信赖的标准却很奇怪——每个人都有一个编号,若两个人可以相互信赖,那么当且仅当这两个编号的素因子集合相同。
那么问题来了:
现在有三个人想组团,请问他们能相互信赖么?
输入
先输入一个正整数T,表示共有T组测试样例,1≤T≤10000。
对于每一个测试样例,输入三个正整数,对于第i个数pi,表示第i个人的编号(1≤pi≤109)。
输出
对于每组样例,如果可以可以成功组团,则输出“YES”,否则输出“NO”。
样例输入
2
3 6 9
3 9 27
样例输出
NO
YES
这道题目拿到手,简单想想,如果真是要算出自然数x的素数集,肯定是TL了。所以,要判断自然数x与y的素数集相同,必须从最大公约数入手。很简单的,求最大公约数的函数int gcd(int, int)如下所示:
int gcd(int x,int y)
{
int c;
while(x%y!=0)
{
c=x%y;
x=y;
y=c;
}
return y;
}
判断两个素数集相等,应该是一件不容易的事情,可以如果要判断一个数的素数集包含另一个数的素数集(即后者的素数集是前者素数集的子集),那就容易多了。
我们假设函数bool contains(int x,int y)来判断x的素数集包含y的素数集,那么判断其素数集相等的函数为:
bool judge(int x,int y)
{
return contains(x,y) && contains(y,x);
}
接下来,完成函数contains()即可。很显然的,我们设g=gcd(x,y)。我们让y充分的去除以g,以至于y尽可能地小。然后递归判断此时的y是否依旧是x素数集的子集。
那么什么情况递归结束呢?显然,当y=1的时候,返回肯定是true。如果y不为1,且x与y互质,则返回肯定是false。
所以contains()函数很容易就写出来了。
bool contains(int x,int y)
{
int g;
if(y==1) return true;
g=gcd(x,y);
if(g==1) return false;
while(y%g==0)
y/=g;
return contains(x,y);
}
最后,我贴出完整的代码:
#include<stdio.h>
#include<math.h>
#include<string.h>
#define MIN(x,y) ((x)<(y)?(x):(y))
#define MAX(x,y) ((x)>(y)?(x):(y))
#define ABS(x) (((x)>0)?(x):(-(x)))
#define bool int
#define true 1
#define false 0
#define TRUE 1
#define FALSE 0
#define int64 long long
#define MAXLEN 1000005
int gcd(int x,int y)
{
int c;
while(x%y!=0)
{
c=x%y;
x=y;
y=c;
}
return y;
}
bool contains(int x,int y)
{
int g;
if(y==1) return true;
g=gcd(x,y);
if(g==1) return false;
while(y%g==0)
y/=g;
return contains(x,y);
}
bool judge(int x,int y)
{
return contains(x,y) && contains(y,x);
}
void main()
{
int n,a,b,c;
scanf("%d",&n);
while(n--)
{
scanf("%d%d%d",&a,&b,&c);
if(judge(a,b) && judge(b,c))
printf("YES\n");
else printf("NO\n");
}
}
结果:Accept