7834:分成互质组
总时间限制: 1000ms 内存限制: 65536kB
描述
给定n个正整数,将它们分组,使得每组中任意两个数互质。至少要分成多少个组?
输入
第一行是一个正整数n。1 <= n <= 10。
第二行是n个不大于10000的正整数。
输出
一个正整数,即最少需要的组数。
样例输入
6
14 20 33 117 143 175
样例输出:
3
来源
2008年第十三届“华罗庚金杯”少年数学邀请赛 决赛第5题
【解析】
本题有两种做法,在此,重点讲述第一种方法,至于各种思路,已迁入代码之中。
方法一:
状态: Accepted
#include<iostream>
using namespace std;
int n,ans=1e9+1;
bool flag;
int a[10010],b[10010];//a[]保存数
int panduan(int a,int b)//递归法判断互质
{
if(b==0)return a;
return panduan(b,a%b);
}
void dfs(int x,int y)//搜到了第x个数,现在有y个集合
{
if(x==n+1)//搜索完成,取最小值,退出
{
ans=min(ans,y);
return;
}
for(int i=1;i<=y;i++)//组数
{
flag=true;
for(int j=1;j<x;j++)//不能加‘=’,因为如果加了‘=’,一个数就可以进这重循环,即x=1时,不可能自己比自己吧。
{
if(b[j]==i)
{
if(panduan(a[x],a[j])!=1)//如果不为互质数
{
flag=false;//就没必要比,再继续加下去了,
break;//跳出
}
}
}
if(flag)//如果前边加的数字都为互质数,就再加数,继续判断
{
b[x]=i;//保存组数
dfs(x+1,y);//加数字,但不加组
b[x]=0;//回溯
}
}
b[x]=y+1;//集合数加1
dfs(x+1,y+1);//进行下一次查找
b[x]=0; //回溯
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
dfs(1,1);//从第一个(数,组)开始
cout<<ans<<endl;
return 0;
}
方法二:
#include<cstdio>
#include<cstring>
int n,a[20],b[20],c=1;
int fun(int x,int y) //递归法判断互质
{
if(!y) return x; //y==0
return fun(y,x%y);
}
int main()
{
memset(b,1,sizeof(b)); //以便于"b[j]*=a[i];"
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
b[1]=a[1];
for(int i=2;i<=n;i++)
{
int j;
for(j=1;j<=c;j++)
if(fun(a[i],b[j])==1) //也就是说两个整数的最大公约数为1,即两个正整数互质
{
b[j]*=a[i];
break;
}
if(j-1==c) //意思就是上面的"break"一次都没有执行
b[++c]=a[i];
}
printf("%d",c);
}