Gym - 101810F Minimum Sum of Array

这题我自己的代码在第二组数据上死都过不去,不知道为什么,现在还是没有找到错误案例,希望有大佬帮我测试一下哪里有错。。。。

我自己的错误代码:

//F
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long LL;
#define MAXN 1000010

int Data[MAXN];
int used[MAXN];

int main()
{
    int i,j,k;
    int N;
    int kase;
    LL sum;
    int num,num2;
    int cnt;

    scanf("%d",&kase);
    while(kase--)
    {
        scanf("%d",&N);
        memset(Data,0,sizeof(Data));
        for(i=1;i<=N;i++)
            scanf("%d",&Data[i]);
        sort(Data+1,Data+1+N);
        sum=0;
        cnt=0;
        memset(used,0,sizeof(used));
        for(i=1;i<=N&&cnt<N;i++)
        {
            if(used[Data[i]])
                continue;
            num=1;
            used[Data[i]]=1;
            while(Data[i]==Data[i+1]&&(i+1)<=N)
            {
                i++;
                num++;
                cnt++;
            }
            sum+=Data[i]*num;
            cnt++;
            for(j=i+1;j<=N&&cnt<N;j++)
            {
                num2=1;
                while(Data[j]==Data[j+1]&&(j+1)<=N)
                {
                    j++;
                    num2++;
                }
                if(Data[j]%Data[i]==0)
                {
                    cnt+=num2;
                    for(k=j-num2+1;k<=j;k++)
                        Data[j]=Data[i];
                    sum+=Data[j]*num2;
                }
            }
        }
        printf("%lld\n",sum);
    }
    return 0;
}

正确的方法普遍有两种:

但是其实都是类似于素数筛法一样的思想,找因数很多技巧也是类似

(1)

https://blog.csdn.net/yz467796454/article/details/81155404

(2)

https://www.cnblogs.com/moomcake/p/9384185.html

其实就是利用map的去重性质

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#include<iostream>
#include<map>
typedef long long ll;
const int MAXN=1000+10;
const int INF=1e6;
using namespace std;
map<ll,ll>::iterator it;
ll dp[1000];
ll l=0;
int main()
{
    ll m,n,t,i;
    //cout<<INF;
    scanf("%lld",&t);
    map<ll,ll>mp;
    while(t--)
    {
        mp.clear();
        scanf("%lld",&m);
        for(ll i=0; i<m; i++)
        {
            scanf("%lld",&n);
            mp[n]++;
        }
        ll ans=0,flag=0;
        for(it=mp.begin(); it!=mp.end(); it++)
        {
            ll k=it->first;
            if(k==1)
            {
                flag=2;
                break;
            }
            ll flag=0,ppq=0;
            for(i=2;i*i<=k;i++)
            {
                if(k%i==0)
                {
                    if(mp.count(i))
                    {
                        mp[i]+=mp[k];
                        it--;
                        mp.erase(k);
                        flag=1;
                        break;
                    }
                    else if(mp.count(k/i))
                    {
                        ppq=k/i;
                    }
                }
            }
            if(!flag)
            {
                if(ppq)
                {
                    mp[ppq]+=mp[k];
                    it--;
                    mp.erase(k);
                }
            }
        }
        if(flag==2)
            printf("%lld\n",m);
        else
        {
            for(it=mp.begin(); it!=mp.end(); it++)
            {
                ans+=it->second*it->first;
            }
            cout<<ans<<endl;
        }
    }
    return 0;
}

详解一下第二种方法的几个细节:

(1)

如果第一位是1,那么所有数都会变成一的,而且不需要事先排序,因为map自身就是从小到大排序的

 

(2)

因为是由小到大的顺序筛选的,所以前面只可能有一个因数,如果有多个那么都是相同的,如2, 4,6,在筛选6的时候4早就变成2了,而且越是前面的数越小,这题就是要找尽量小的数。

(3)

else if之所以不用break,是因为有可能还有比i大的因数但是比sqrt(k)小的数,这是比ppq更优的解,因为更小一点,所以应该继续枚举下去。

而且

之所以要有这句话,是因为虽然素数筛法里面>sqrt(k)的数在后面会被更大的数筛掉,但是这里不一样,比如:

4,12,16,sqrt(12)<4,所以会将ppq标记为4,所以如果没有else if这句话,4自然会被16筛掉,但是12仍然是12,没有变成3,所以答案错误!!!!

(4)

注意,一定要it--,因为不然会变成野指针

为什么不能是it++?

因为最外层的for循环有紧接着这句话的it++

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值