Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 80 Accepted Submission(s): 39
5 1 4 2 3 9 0
136HintIn the sample, b1=1, c1=4, b2=4, c2=4, b3=4, c3=2, b4=3, c4=9, b5=9, c5=9, so b1 * c1 + b2 * c2 + … + b5 * c5 = 136.
题目中要求计算出第i个数a[i]之前和之后距离i最近的两个a[i]的乘积(如果没有,那就选择a[i]),再把所有的乘积累加起来.
因为给出的是随机数据,所以每个数出现的概率相同,也就是说给出的a[i]大部分都会在几十,几百,或者更高,从前向后遍历,哈希出每个数出现的最近的情况,对于每一个要判断的数,从0倍开始不断增加,一直到maxn,统计所有出现过的倍数,和位置最接近那个数的点,如果没有,就记录自身,得到所有数的前面的倍数是那个,同样的方法得到后面的倍数,相乘累加。
如果a[i]是1,那么不节约时间,a[i]是10,最多用10000/10 ,a[i]是100 用时10000/100,
#include <cstring> #include <cstdio> #include <math.h> #include <algorithm> using namespace std; #define LL __int64 struct node { LL num, f; }_hash[110000]; LL a[110000], b[110000], c[110000]; int main() { LL n, i, j, sum, max1, mmax; LL ans; while(scanf("%I64d",&n)!=EOF&&n) { max1=-1; for(i=1;i<=n;i++) { scanf("%I64d",&a[i]); if(max1<a[i]) max1=a[i]; } for(i=1;i<=max1;i++) _hash[i].f=0; for(i=1;i<=n;i++) { mmax=-1; for(j=a[i];j<=max1;j+=a[i]) { if(_hash[j].f) { if(mmax<_hash[j].num) { mmax=_hash[j].num; } } } _hash[a[i]].f=1; _hash[a[i]].num=i; if(mmax==-1) b[i]=a[i]; else b[i]=a[mmax]; } for(i=1;i<=max1;i++) _hash[i].f=0; for(i=n;i>=1;i--) { mmax=1e7;; for(j=a[i];j<=max1;j+=a[i]) { if(_hash[j].f) { if(mmax>_hash[j].num) { mmax=_hash[j].num; } } } _hash[a[i]].f=1; _hash[a[i]].num=i; if(mmax==1e7) c[i]=a[i]; else c[i]=a[mmax]; } ans=0; for(i=1;i<=n;i++) { ans+=b[i]*c[i]; //printf("b==%d c==%d\n",b[i],c[i]); } printf("%I64d\n",ans); } return 0; }