hdu4961 Boring Sum(数学)

来源:互联网 发布:魔兽世界网络卡 编辑:程序博客网 时间:2024/05/17 01:57

题目:

Boring Sum

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1213    Accepted Submission(s): 569


Problem Description
Number theory is interesting, while this problem is boring.

Here is the problem. Given an integer sequence a1, a2, …, an, let S(i) = {j|1<=j<i, and aj is a multiple of ai}. If S(i) is not empty, let f(i) be the maximum integer in S(i); otherwise, f(i) = i. Now we define bi as af(i). Similarly, let T(i) = {j|i<j<=n, and aj is a multiple of ai}. If T(i) is not empty, let g(i) be the minimum integer in T(i); otherwise, g(i) = i. Now we define ci as ag(i). The boring sum of this sequence is defined as b1 * c1 + b2 * c2 + … + bn * cn.

Given an integer sequence, your task is to calculate its boring sum.
 

Input
The input contains multiple test cases.

Each case consists of two lines. The first line contains an integer n (1<=n<=100000). The second line contains n integers a1, a2, …, an (1<= ai<=100000).

The input is terminated by n = 0.
 

Output
Output the answer in a line.
 

Sample Input
51 4 2 3 90
 

Sample Output
136
Hint
In 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.
 

Author
SYSU
 

Source
2014 Multi-University Training Contest 9
 

题意:给一个数组,定义f[i]是左边最靠近a[i]并且是a[i]倍数的值的下标,g[i]右边最靠近a[i]并且是a[i]倍数的值的下标,b[i]=a[f[i]],c[i]=a[g[i]],求b1*c1+b2*c2+...+bn*cn.

思路:其实就是怎么快速找出最靠近一个数并且是它倍数的数。我们可以先暴力枚举出每个数的约数(用类似素数筛法的方法,nlogn),然后用一个数组来维护一个约数最后出现的位置。先从左往右枚举数组中的每一个元素,如果它已经出现在了约数数组里,那么对应的约数数组的值就是它的左边最靠近它的倍数的下标。然后将它的左右约数填进约数数组里。再从右往左枚举数组就得到了它的右边最靠近它的倍数的下标。

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<vector>using namespace std;const int MAXN=100000;int a[MAXN+5];vector<int>f[MAXN+5];int F[MAXN+5],G[MAXN+5];int b[MAXN+5],c[MAXN+5];void init(){for(int i=1;i<=MAXN;i++)f[i].clear();for(int i=1;i<=MAXN;i++)for(int j=i;j<=MAXN;j+=i)f[j].push_back(i);}int vis[MAXN+5];int main(){int n;init();while(scanf("%d",&n)!=EOF){if(!n)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]]){vis[a[i]]=i;F[i]=i;}else{F[i]=vis[a[i]];vis[a[i]]=i;}for(int j=0;j<f[a[i]].size();j++){vis[f[a[i]][j]]=i;}}//printf("%d ",F[i]);//printf("\n");memset(vis,0,sizeof(vis));for(int i=n;i>=1;i--){if(!vis[a[i]]){vis[a[i]]=i;G[i]=i;}else{G[i]=vis[a[i]];}for(int j=0;j<f[a[i]].size();j++){vis[f[a[i]][j]]=i;}}__int64 ans=0;for(int i=1;i<=n;i++){b[i]=a[F[i]];c[i]=a[G[i]];ans=ans+(__int64)b[i]*c[i];}printf("%I64d\n",ans);}return 0;}


0 0
原创粉丝点击