Boring Sum
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 450 Accepted Submission(s): 228
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
5
1 4 2 3 9
0
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
题意:给你一串数,转化出b数组和c数组,然后求出b[i]*c[i]之和,b数组就是在这个位置的左边最靠近他的倍数的数,c就是在右边最靠近他且是他的倍数的数,没有倍数就是原数。
首先看到这题的时候直接暴力搞(TLE),从左到右扫,对每个位置的数,看右边的数有没有他的约数,是他的约数就变成这个数,然后同理再从右到左。。这样复杂度就是O(n^2).毫无意外的TLE。
然后开始加一些优化,发现每个数的约数都是固定的,预处理(打表),筛选法筛选出每个数的约数,然后再从左到右扫,每扫到一个数就把这个数的约数做个标记,而后每个数判断有没有约数标记,有的话代替就是,同理从右往左一遍。。。时间复杂度O(n)..
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=100010;
vector<int> G[MAXN];
int a[MAXN],b[MAXN],c[MAXN];
int id[MAXN];
int main()
{
int i,j,n;
for(i=1;i<MAXN;i++)
{
for(j=1;j<MAXN/i;j++)
G[i*j].push_back(i);
}
while(scanf("%d",&n)!=EOF&&n)
{
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
memset(id,0,sizeof(id));
for(i=0;i<n;i++)
{
if(!id[a[i]])
b[i]=a[i];
else
b[i]=id[a[i]];
for(j=0;j<G[a[i]].size();j++)
id[G[a[i]][j]]=a[i];
}
memset(id,0,sizeof(id));
for(i=n-1;i>=0;i--)
{
if(!id[a[i]])
c[i]=a[i];
else
c[i]=id[a[i]];
for(j=0;j<G[a[i]].size();j++)
id[G[a[i]][j]]=a[i];
}
__int64 ans=0;
for(i=0;i<n;i++)
ans+=(__int64)b[i]*(__int64)c[i];
printf("%I64d\n",ans);
}
return 0;
}