当前位置: 代码迷 >> 综合 >> 信息学奥赛一本通 1221:分成互质组(evd)
  详细解决方案

信息学奥赛一本通 1221:分成互质组(evd)

热度:27   发布时间:2024-03-05 22:49:08.0

题目描述】
给定n个正整数,将它们分组,使得每组中任意两个数互质。至少要分成多少个组?

【输入】
第一行是一个正整数n。1 ≤ n ≤ 10。

第二行是n个不大于10000的正整数。

【输出】
一个正整数,即最少需要的组数。

【输入样例】
6
14 20 33 117 143 175
【输出样例】
3
【心得】第一份代码是自己写的,虽然一遍过了,但是总觉着搜索的不纯粹,加了些模拟的味道。提前计算出任何两个数的互质关系,每次先新建一个分组,再把满足两两互质的数都放到该组里,之后再进行下一层搜索。最终所有数都会进入相应的组。
【AC代码1】

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int cnt,n,a[15],f[15],vis[15][15];
int gcd(int x,int y)
{
    return y==0?x:gcd(y,x%y);
}
void dfs(int x)
{
    if(cnt==n){
    cout<<x-1;return ;}for(int i=0;i<n;i++){
    if(f[i]==0){
    f[i]=x;cnt++;break;}}for(int i=0;i<n;i++){
    if(f[i]==0){
    bool flag=true;for(int j=0;j<n;j++){
    if(i!=j&&f[j]==x&&vis[j][i]==0){
    flag=false;break;}}if(flag) {
    f[i]=x;cnt++;}}	}dfs(x+1);
}
int main()
{
    cin>>n;for(int i=0;i<n;i++) cin>>a[i];for(int i=0;i<n;i++){
    for(int j=i;j<n;j++){
    if(gcd(a[i],a[j])==1)vis[i][j]=1;}}dfs(1);return 0;
}

【AC代码2】参考别人的,深深感到自身的不足

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
int n,a[15],cnt=10;
long long int vis[15];//多个数得到积,int可能装不下
long long int gcd(long long int a,long long int b){
    return b==0?a:gcd(b,a%b);}
void dfs(int k,int step) //优美的模板格式
{
    if(step==n+1){
    if(k<cnt) cnt=k;return;}for(int i=1;i<=k;i++)if(gcd(vis[i],a[step])==1)//加入已有组,判断其与组内所有数都互质 {
    vis[i]*=a[step];//乘积互质则两两互质dfs(k,step+1);vis[i]/=a[step];}vis[k+1]*=a[step];//新建分组 dfs(k+1,step+1);vis[k+1]/=a[step];
}
int main()
{
    cin>>n;for(int i=1;i<=n;i++) cin>>a[i],vis[i]=1;dfs(1,1);cout<<cnt<<endl;return 0;
}