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