You are given an array a consisting of n integers a1, ..., an. In one operation, you can choose 2 elements ai and aj in which ai is divisible by aj and transform ai to aj.
A number x is said to be divisible by a number y if x can be divided by y and the result is an exact whole number. For example, 15 is divisible by 3, because 15÷ 3 = 5 exactly, but 9 is not divisible by 2 because 9÷ 2 is 4 with 1 left over.
Your task is to find the minimum sum of the array a that can be obtained by making as many transform operations as you want. Can you?
Input
The first line contains an integer T (1 ≤ T ≤ 100) specifying the number of test cases.
The first line of each test case contains an integer n (1 ≤ n ≤ 105), in which n is the size of array a. Then a line follows containing n integers a1, ..., an (1 ≤ ai ≤ 106), giving array a.
The sum of n overall test cases does not exceed 3 × 106.
Output
For each test case, print a single line containing the minimum sum of the array a that can be obtained after making as many transform operations as you want.
Example
Input
1
5
2 2 3 6 6
Output
11
题意:若数组中的一个数a能被另一个数b整除,则可以用b替换掉a,经过多次操作后,使得该数组的和尽可能的小,并输出这个最小值。
思路:在每个数的所有因子中,找到那个在题目所给数组中并且最小的那个因子,用这个因子替换掉这个数。
代码实现:map记录每个数出现的次数,用迭代器遍历map,找到每个数那个满足条件的最小因子,(求因子时注意用sqrt优化)并替换之(直接让因子出现的个数加上那个数出现的个数,再将那个数删掉)
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <stack>
#include <queue>
#include <deque>
#include <cstdio>
#include <vector>
#include <numeric>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define eps 1e-8
#define PI acos(-1)
#define INF 1e6+100
using namespace std;
const int N=10000 + 10 ;
typedef long long LL;
const int dir[4][2]= { {1,0},{0,1},{-1,0},{0,-1} };
int GCD(int a,int b)
{
return b ? GCD(b,a%b) : a;
}
map<LL,LL>::iterator it;
int main()
{
int T;
cin>>T;
while(T--)
{
map<LL,LL>mp;
stack<LL>p;
mp.clear();
LL i,j,n,z=0;
LL rep,ans=0,flag=0;
scanf("%lld",&n);
for(i=0; i<n; i++)
{
scanf("%lld",&rep);
mp[rep]++;
}
for(it=mp.begin(); it!=mp.end(); it++)
{
LL j=it->first;
if(j==1)
{
flag=1;
break;
}
else if(j>3)
{
LL g=0,nflag=0;
LL ans[N]= {0};
for(LL i=2; i*i<=j; i++)
{
if(j%i==0)
{
if(mp.count(i))
{
mp[i]+=mp[j];
it--;
mp.erase(j);
nflag=1;
break;
}
if(mp.count(j/i))
{
p.push(j/i);
g++;
}
}
}
if(!nflag)
{
if(g!=0)
{
mp[p.top()]+=mp[j];
it--;
mp.erase(j);
}
}
}
}
if(flag)
ans=n;
else
{
for(it=mp.begin(); it!=mp.end(); it++)
{
ans+=it->second*it->first;
}
}
printf("%lld\n",ans);
}
return 0;
}
通过替换操作,寻找数组中每个数的最小因子,并替换以达到数组和最小化的目标。

被折叠的 条评论
为什么被折叠?



