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?
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.
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.
1
5
2 2 3 6 6
11
题目意思:有一个长度为n的数组,对于数组中的两个元素x,y如果满足y%x==0,则可以将y转换成x,求经过多次变换后数组的前n项和最小是多少。
由于数据量较大我们选择了map这一容器来去重。对容器中的每一个元素遍历,开始我的打算是将每一个元素的因子都拆分,再按照从小到大的顺序来一一枚举因子(因为如果容器中有元素等于交小的因子
替换后得到的答案就是最小的),可惜超时了,于是寻求另一种方法来解决。我同学给我提供了一个新的思路,我们在求某一个数的因子的时候,为了优化算法,降低时间复杂度,会采用一种方法,比如求
12的因子的时候,我们从1到12逐个遍历,知道2是12的因子,那么也能得到12/2=6也是12的因子;知道了3是12的因子,那么也同时得到了4也是12的因子。这里也是一样的,我们也是先依次去从小的因子
出发,找小的因子的过程中也找到了其对应的比其大的因子。如果小因子不存在,再看看对应的较大的那个因子是否存在,存在的话就保存下来。之后也是这样增大因子,重复这个过程,要是存在对应的交大的因子就更新保存的结果,这些较小的因子都找过了依旧不满足条件,那么就找那个保存的那个较大的因子。
还需要注意的是mp.erase(),当在迭代器中调用这个函数的话,需要先返回上一个迭代器,不然指针会变为一个野指针(可参考链表理解)。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<map> 5 #define LL long long int 6 using namespace std; 7 int main() 8 { 9 int t,flag,flag1; 10 LL i,j,a,n,k; 11 LL ans,x; 12 map<LL,LL>mp; 13 map<LL,LL>::iterator it; 14 scanf("%d",&t); 15 while(t--) 16 { 17 mp.clear(); 18 scanf("%lld",&n); 19 for(i=0;i<n;i++) 20 { 21 scanf("%lld",&a); 22 mp[a]++; 23 } 24 flag=0; 25 ans=0; 26 for(it=mp.begin();it!=mp.end();it++) 27 { 28 k=it->first; 29 if(k==1)///出现1 30 { 31 flag=1; 32 break; 33 } 34 flag1=0; 35 x=0; 36 for(i=2;i*i<=k;i++) 37 { 38 if(k%i==0) 39 { 40 if(mp.count(i)) 41 { 42 mp[i]+=mp[k]; 43 it--; 44 mp.erase(k); 45 flag1=1; 46 break; 47 } 48 else if(mp.count(k/i)) 49 { 50 x=k/i; 51 } 52 } 53 } 54 if(!flag1) 55 { 56 if(x) 57 { 58 mp[x]+=mp[k]; 59 it--; 60 mp.erase(k); 61 } 62 } 63 } 64 if(flag) 65 { 66 printf("%lld ",n); 67 } 68 else 69 { 70 for(it=mp.begin();it!=mp.end();it++) 71 { 72 ans+=it->second*it->first; 73 } 74 printf("%lld ",ans); 75 } 76 } 77 return 0; 78 }