kotori拿到了一些正整数。她决定从每个正整数取出一个素因子。但是,kotori有强迫症,她不允许两个不同的正整数取出相同的素因子。
她想知道,最终所有取出的数的和的最小值是多少?
注:若a%k==0,则称k是a的因子。若一个数有且仅有两个因子,则称其是素数。显然1只有一个因子,不是素数。
输入描述:
第一行一个正整数n,代表kotori拿到正整数的个数。
第二行共有n个数ai,表示每个正整数的值。
保证不存在两个相等的正整数。
1<=n<=10
2<=ai<=1000
输出描述:
一个正整数,代表取出的素因子之和的最小值。若不存在合法的取法,则输出-1。
示例1
输入
复制
4
12 15 28 22
输出
17
说明
分别取3,5,7,2,可保证取出的数之和最小
示例2
输入
5
4 5 6 7 8
输出
-1
备注:
1<=n<=10
2<=ai<=1000
题目大意 :输入 N 个数, 从这N个数中各取一个素因子, 求和的最小值。
思路 :看了眼数据,不是很大,加上又是素数又是因子的,直接用邻接表存每个数的素因子,然后DFS搜一下就过了。注意下找因子的时候要带上1和N, 在求素数的过程中要把1给去掉。
AC代码 :
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e3 + 5;
const int INF = 0x3f3f3f3f;
int n, m, sum, min_, X;
vector <int> e[maxn];
bool vis[maxn], flag;
bool fun (int n) { // 是否为素数
if (n == 1) return false;
for (int i = 2; i <= floor (sqrt(n)); i++) {
if (n % i == 0) return false;
}
return true;
}
void prime (int n, int x) { //找素因子
for (int i = 1; i <= floor (sqrt(n)); i++) {
if (n % i == 0) {
if (fun (i)) e[x].push_back(i);
if (i * i != n && fun (n / i)) e[x].push_back(n / i); //存数
}
}
}
void dfs(int y) {
if (y == X) {
flag = 1;
min_ = min (min_, sum);
return;
}
for (int i = 0; i < e[y].size(); i++) {
if (!vis[e[y][i]]) {
sum += e[y][i];
vis[e[y][i]] = 1;
dfs(y + 1);
vis[e[y][i]] = 0;
sum -= e[y][i];
}
}
}
int main()
{
cin >> n;
for (int i = 0; i < n; i++) {
cin >> m;
prime (m, X++);
}
min_ = INF;
dfs(0);
if (flag) cout << min_ << endl;
else cout << -1 << endl;
return 0;
}