HDU4961 Boring Sum

本文详细介绍了BoringSum问题的求解方法,包括原始暴力解法的时间复杂度分析,以及通过预处理优化后的算法实现,使得整体时间复杂度降低至O(n),并提供了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值