【题意】给n个数字 求每个数字 左边的数字中是其倍数的且下标最大 的数字*右边的倍数中是其倍数的且下标最小的数字 的和
或者说就是每个数 左边最近的倍数*右边最近的倍数 的和。
http://acm.hdu.edu.cn/showproblem.php?pid=4961
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 using namespace std; 6 7 int a[100002],b[100002],c[100002]; 8 int vis[100002]; 9 10 int main() 11 { 12 int n; 13 while(~scanf("%d",&n)&&n) 14 { 15 for(int i=1;i<=n;i++) 16 scanf("%d",&a[i]); 17 memset(vis,0,sizeof(vis)); //值i倍数且是在左边的中对应的最大下标 18 for(int i=1;i<=n;i++) 19 { 20 if(vis[a[i]]) 21 b[i]=a[vis[a[i]]]; 22 else b[i]=a[i]; 23 for(int j=1;j<(int)sqrt((double)a[i])+1;j++) 24 { 25 if(a[i]%j==0) 26 { 27 vis[a[i]/j]=i; 28 vis[j]=i; 29 } 30 }//更新的都是i右边的约数,因为i和i前面的都已经得出来了 。由于i是小到大,所有得到的值也是最大的。 31 } 32 33 memset(vis,0,sizeof(vis)); //值i倍数且是在右边的对应的最小下标 34 for(int i=n;i>=1;i--) 35 { 36 if(vis[a[i]]) 37 c[i]=a[vis[a[i]]]; 38 else c[i]=a[i]; 39 40 for(int j=1;j<(int)sqrt((double)a[i])+1;j++) 41 { 42 if(a[i]%j==0) 43 { 44 vis[a[i]/j]=i; 45 vis[j]=i; 46 } 47 }//更新的都是i左边的约数的vis值,因为i和i后面的都已经得出来了。由于i是小到大,所以得到的值也是最小的 48 } 49 __int64 ans=0; 50 for(int i=1;i<=n;i++) 51 ans+=(__int64 )b[i]*c[i]; 52 printf("%I64d ",ans); 53 } 54 return 0; 55 }