http://acm.hdu.edu.cn/showproblem.php?pid=4961
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.
给出n个数的数列a,bi的取值为在1 <= j < i之间如果存在aj % ai == 0,则取最大下标的值赋给bi,如果不存在,则bi = ai;ci的取值为在i < j <= n之间如果存在aj % ai == 0,则取最小下标值赋给bi,如果不存在,则ci = ai。求b1 * c1 + b2 * c2 + ... + bn * cn的和。
思路:
如果直接暴力的话一定会超时,所以我们可以开一个vis数组来记录每一个值所对应的最大的下标是多少。即每查找ai,分解出ai的质因子,更新vis数组。
#include <stdio.h> #include <string.h> #include <iostream> #include <cmath> using namespace std; typedef __int64 LL; int a[100005],vis[100005],b[100005],c[100005],n; int main() { while(~scanf("%d",&n)) { if(n==0) break; for(int i=1; i<=n; i++) scanf("%d",&a[i]); memset(vis,0,sizeof(vis)); for(int i=1; i<=n; i++) { if(vis[a[i]]) b[i]=a[vis[a[i]]]; else b[i]=a[i]; for(int j=1; j<=(int)sqrt((double)a[i]) + 1; j++) { if(a[i]%j==0) { vis[a[i]/j]=i; vis[j]=i; } } } memset(vis,0,sizeof(vis)); for(int i=n; i>=1; i--) { if(vis[a[i]]) c[i]=a[vis[a[i]]]; else c[i]=a[i]; for(int j=1; j<=(int)sqrt((double)a[i])+1; j++) { if(a[i]%j==0) { vis[a[i]/j]=i; vis[j]=i; } } } /* for(int i=1;i<=n;i++) printf("%d ",b[i]); printf("\n"); for(int j=1;j<=n;j++) printf("%d ",c[j]); printf("\n"); */ LL ans=0; for(int i=1; i<=n; i++) ans+=(LL)b[i]*c[i]; printf("%I64d\n",ans); } return 0; }