Minimum Sum of Array(map)

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
题解:有一个长度为n的数组,对于数组中的两个元素x,y如果满足y%x==0,则可以将y转换成x,求经过多次变换后数组的前n项和最小是多少。由于数据量很大,我们可以用map(去重),对容器中的每一个元素便历,对x的每一因子xi从小到大枚举,如果xi在容器中,则将x转换成xi,并结束循环,在求x的因子时如果将因子存进数组中在sort,会超时,所以我用了一个小技巧,闲话少说看代码。还需要注意的是mp.erase(),当在迭代器中调用这个函数的话,需要先返回上一个迭代器,不然指针会变为一个野指针(可参考链表理解),我在这个地方卡了好久哦。
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<stack>
 6 #include<iostream>
 7 #include<map>
 8 typedef long long ll;
 9 const int MAXN=1000+10;
10 const int INF=1e6;
11 using namespace std;
12 map<ll,ll>::iterator it;
13 ll dp[1000];
14 ll l=0;
15 int main()
16 {
17     ll m,n,t,i;
18     //cout<<INF;
19     scanf("%lld",&t);
20     map<ll,ll>mp;
21     while(t--)
22     {
23         mp.clear();
24         scanf("%lld",&m);
25         for(ll i=0; i<m; i++)
26         {
27             scanf("%lld",&n);
28             mp[n]++;
29         }
30         ll ans=0,flag=0;
31         for(it=mp.begin(); it!=mp.end(); it++)
32         {
33             ll k=it->first;
34             if(k==1)
35             {
36                 flag=1;
37                 break;
38             }
39             ll flag=0,ppq=0;
40             for(i=2;i*i<=k;i++)
41             {
42                 if(k%i==0)
43                 {
44                     if(mp.count(i))
45                     {
46                         mp[i]+=mp[k];
47                         it--;
48                         mp.erase(k);
49                         flag=1;
50                         break;
51                     }
52                     else if(mp.count(k/i))
53                     {
54                         ppq=k/i;
55                     }
56                 }
57             }
58             if(!flag)
59             {
60                 if(ppq)
61                 {
62                     mp[ppq]+=mp[k];
63                     it--;
64                     mp.erase(k);
65                 }
66             }
67         }
68         if(flag)
69             printf("%lld\n",m);
70         else
71         {
72             for(it=mp.begin(); it!=mp.end(); it++)
73             {
74                 ans+=it->second*it->first;
75             }
76             cout<<ans<<endl;
77         }
78     }
79     return 0;
80 }
View Code

 

posted @ 2018-07-29 07:25  左手边五十米  阅读(264)  评论(0编辑  收藏  举报