hdu 4961 Boring Sum n*logn

【题意】给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\n",ans);
53     }
54     return 0;
55 }

 

posted @ 2014-08-20 16:08  galaxy77  阅读(296)  评论(0编辑  收藏  举报