Minimum Sum of Array(map迭代器)

codeforces 910c

 

转自两位大佬:http://www.cnblogs.com/wkfvawl/p/9387634.html

https://i.cnblogs.com/EditPosts.aspx?opt=1

 

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这一容器来去重。对容器中的每一个元素遍历,开始我的打算是将每一个元素的因子都拆分,再按照从小到大的顺序来一一枚举因子(因为如果容器中有元素等于交小的因子
替换后得到的答案就是最小的),可惜超时了,于是寻求另一种方法来解决。我同学给我提供了一个新的思路,我们在求某一个数的因子的时候,为了优化算法,降低时间复杂度,会采用一种方法,比如求
12的因子的时候,我们从1到12逐个遍历,知道2是12的因子,那么也能得到12/2=6也是12的因子;知道了3是12的因子,那么也同时得到了4也是12的因子。这里也是一样的,我们也是先依次去从小的因子
出发,找小的因子的过程中也找到了其对应的比其大的因子。如果小因子不存在,再看看对应的较大的那个因子是否存在,存在的话就保存下来。之后也是这样增大因子,重复这个过程,要是存在对应的交大的因子就更新保存的结果,这些较小的因子都找过了依旧不满足条件,那么就找那个保存的那个较大的因子。
还需要注意的是mp.erase(),当在迭代器中调用这个函数的话,需要先返回上一个迭代器,不然指针会变为一个野指针(可参考链表理解)。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define LL long long int
using namespace std;
int main()
{
    int t,flag,flag1;
    LL i,j,a,n,k;
    LL ans,x;
    map<LL,LL>mp;
    map<LL,LL>::iterator it;
    scanf("%d",&t);
    while(t--)
    {
        mp.clear();
        scanf("%lld",&n);
        for(i=0;i<n;i++)
        {
            scanf("%lld",&a);
            mp[a]++;
        }
        flag=0;
        ans=0;
        for(it=mp.begin();it!=mp.end();it++)
        {
            k=it->first;
            if(k==1)///出现1
            {
                flag=1;
                break;
            }
            flag1=0;
            x=0;
            for(i=2;i*i<=k;i++)
            {
                if(k%i==0)
                {
                    if(mp.count(i))//查看i有没有  存在返回1,不存在返回0;
                    {
                        mp[i]+=mp[k];
                        it--;
                        mp.erase(k);
                        flag1=1;
                        break;
                    }
                    else if(mp.count(k/i))
                    {
                        x=k/i;
                    }
                }
            }
            if(!flag1)
            {
                if(x)
                {
                    mp[x]+=mp[k];
                    it--;
                    mp.erase(k);//清空这一列
                }
            }
        }
        if(flag)
        {
            printf("%lld\n",n);
        }
        else
        {
            for(it=mp.begin();it!=mp.end();it++)
            {
                ans+=it->second*it->first;
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}

 



posted @ 2018-08-08 14:47  我的秘密小屋  阅读(168)  评论(0编辑  收藏  举报