来源: 2014 Multi-University Training Contest 9
参考: 林燕同学的博客
做题感受: 比赛时坚持了原始朴素的遍历法,不出意外的TLE,最后是小伙伴把它A掉了,但是他的代码我看不懂(忧桑)。赛后看了题解,
感觉智商不够用,最后还是百度了先A者的做题代码,敲完了,琢磨了许久,脑子才转过弯来。
参考代码如下:
#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
#define SIZE 100005
#define m(a,b) memset(a,b,sizeof(a))
int a[SIZE],b[SIZE],c[SIZE],p[SIZE];
int main()
{
int n,i,j;
__int64 sum;
while(scanf("%d",&n),n!=0)
{
sum=0;
m(p,-1);
for(i=0;i<n;i++) //自左向右扫描
{
scanf("%d",&a[i]);
if(p[a[i]]>-1) //存在能被a[i]整除的数,该数必是离当前数最近且为a[i]的倍数
b[i]=p[a[i]];
else
b[i]=i; //a[i]左侧不存在能被a[i]整除的数
for(j=1;j*j<=a[i];j++)
{
if(a[i]%j==0) //更新a[i]各因子所对应的最大的数列元素下标,
//保证下次查询元素倍数时找到的元素是离查询元素最近的倍数
{
p[j]=i;
p[a[i]/j]=i;
}
}
}
m(p,-1);
for(i=n-1;i>=0;i--) //自右向左扫描
{
if(p[a[i]]>-1)
c[i]=p[a[i]];
else
c[i]=i; //a[i]右侧不存在能被a[i]整除的数
for(j=1;j*j<=a[i];j++)
{
if(a[i]%j==0)
{
p[j]=i;
p[a[i]/j]=i;
}
}
}
for(i=0;i<n;i++)
sum=sum+(__int64)a[b[i]]*a[c[i]];
printf("%I64d\n",sum);
}
return 0;
}