1221:分成互质组

【题目描述】

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

【输入】

第一行是一个正整数n。1 ≤ n ≤ 10。

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

【输出】

一个正整数,即最少需要的组数。

【输入样例】

6
14 20 33 117 143 175

【输出样例】

3

【AC代码】

#include <bits/stdc++.h>
using namespace std;
int n,t,a[11][15],ans=1;
int main()
{
  cin>>n;
  cin>>a[1][1];
  a[1][0]=1;
  n--;
  while(n--)
  {
    cin>>t;
    bool ok=false;
    for(int i=1; i<=ans; i++)
    {
      bool fnd=false;
      for(int j=1; j<=a[i][0]; j++)
      {
        if(__gcd(a[i][j],t)!=1)
        {
          fnd=true;
          break;
        }
      }
      if(!fnd)
      {
        a[i][0]++;
        a[i][a[i][0]]=t;
        ok=true;
        break;
      }
    }
    if(!ok)
    {
      ans++;
      a[ans][1]=t;
      a[ans][0]=1;
    }
  }
  cout<<ans<<endl;
  return 0;
}

### 问题分析 将一正整数分成若干,使得每中任意两个数互质(即它们的最大公约数为 1),目标是找出最少的分数。该问题属于典型的搜索与剪枝优化问题,通常采用深度优先搜索(DFS)结合剪枝策略来实现。 在搜索过程中,对于每一个数,可以选择将其放入已有的某个中(前提是它与该所有元素互质),或者新开一个。通过尝试所有可能的合,并在过程中进行剪枝(如提前终止无效路径),可以高效地找到最优解。 ### 算法实现 以下是一个基于 DFS 的 C++ 实现,它尝试将每个数放入当前已有中或新开一,并维护最小分数: ```cpp #include <bits/stdc++.h> using namespace std; int n, minGroups = 18; // 初始最小分数设为一个较大值 int group[18]; // group[i] 表示第 i 当前所有数的乘积 int a[18]; // 输入的数 bool used[18]; // 标记是否已处理该数 // 判断当前数是否可以加入该 bool canAdd(int idx, int g) { for (int i = 1; i <= n; i++) { if (used[i] && group[i] == g) { if (__gcd(a[idx], a[i]) != 1) return false; } } return true; } void dfs(int idx, int k) { if (k >= minGroups) return; // 剪枝:当前分已不小于最优解 if (idx > n) { minGroups = k; return; } for (int i = 1; i <= k; i++) { if (canAdd(idx, i)) { group[i] *= a[idx]; dfs(idx + 1, k); group[i] /= a[idx]; } } // 开新 group[k + 1] = a[idx]; dfs(idx + 1, k + 1); group[k + 1] = 1; } int main() { cin >> n; for (int i = 1; i <= n; i++) { cin >> a[i]; group[i] = 1; } dfs(1, 0); cout << minGroups << endl; return 0; } ``` ### 核心思想 - **递归搜索**:对每一个数尝试将其放入已有或新开一。 - **剪枝优化**:当当前分数已经不小于已知的最小分数时,直接终止该分支的搜索。 - **状态表示**:使用 `group[i]` 表示第 `i` 所有数的乘积,用于快速判断新数是否与内所有数互质[^1]。 - **贪心优化**:优先尝试将数放入已有,而不是新开,从而更快找到更优解。 ### 时空复杂度分析 - 时间复杂度:最坏情况下为 $ O(N \cdot 2^N) $,但由于剪枝机制,实际运行效率较高。 - 空间复杂度:$ O(N) $,用于存储分状态和递归栈。 ### 应用场景 该算法适用于小规模数据集(如 $ N \leq 15 $)下的最优分问题,可广泛应用于合优化、图的着色问题、数论分等领域。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值