题目链接:https://ac.nowcoder.com/acm/contest/940/E/
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
kotori拿到了一些正整数。她决定从每个正整数取出一个素因子。但是,kotori有强迫症,她不允许两个不同的正整数取出相同的素因子。
她想知道,最终所有取出的数的和的最小值是多少?
注:若a%k==0,则称k是a的因子。若一个数有且仅有两个因子,则称其是素数。显然1只有一个因子,不是素数。
输入描述
第一行一个正整数n,代表kotori拿到正整数的个数。
第二行共有n个数ai,表示每个正整数的值。
保证不存在两个相等的正整数。
1<=n<=10,2<=ai<=1000
输出描述
一个正整数,代表取出的素因子之和的最小值。若不存在合法的取法,则输出-1。
输入
4
12 15 28 22
5
4 5 6 7 8
输出
17
-1
说明
样例1:分别取3,5,7,2,可保证取出的数之和最小
备注
1<=n<=10,2<=ai<=1000
解题思路
题意:每个都贡献一个素因子,保证所有的素因子互不相同,求素因子和的最小值。
思路:线性筛出1~1000之内的所有素数,然后DFS求解最小值。
Accepted Code:
#include <bits/stdc++.h>
using namespace std;
const int MAXM = 1005;
const int inf = 0x3f3f3f3f;
bool isprime[MAXM];
int n, cnt = 0, min_ = inf, s[15], pre[MAXM], vis[MAXM];
void prime() {
isprime[0] = isprime[1] = true;
for (int i = 2; i < MAXM; i++) {
if (!isprime[i])
pre[cnt++] = i;
for (int j = 0; j < cnt && i * pre[j] < MAXM; j++) {
isprime[i *pre[j]] = true;
if (!(i % pre[j]))
break;
}
}
}
void DFS(int x, int ans) {
if (x >= n) {
if (min_ > ans)
min_ = ans;
return ;
}
for (int i = 0; i < cnt; i++) {
if (!(s[x] % pre[i]) && !vis[pre[i]]) {
vis[pre[i]] = true;
DFS(x + 1, ans + pre[i]);
vis[pre[i]] = false;
}
}
}
int main() {
prime();
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &s[i]);
DFS(0, 0);
if (min_ < inf)
printf("%d\n", min_);
else printf("-1\n");
return 0;
}