题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4961
5 1 4 2 3 9 0
136HintIn 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.
题意:
给出一个数列:a[i],然后
b[i]:表示在 i 前面的项,如果有a[i]的倍数(要最靠近i的),那么b[i]就等于这个数,如果没有那么b[i] = a[i];
c[i]:表示在 i 后面的项,如果有a[i]的倍数(要最靠近i的),那么c[i] 就等于这个数,如果没有那么c[i] = a[i];
思路:
//先打表,把每个数的约数存在vector里;
//然后从前往后扫一遍,结果存在b[i],
//Ps:如果不清楚为什么从前往后扫一遍就是最靠近的那个数可调试一下(案例:9 6 3 2 1);
//然后从后往前扫一遍,结果存在c[i],
//Ps:如果不清楚为什么从后往前扫一遍就是最靠近的那个数可调试一下(案例:1 2 3 6 9);
//最后计算b[i]*c[i]的和即可。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define maxn 100000+17
using namespace std;
typedef __int64 LL;
int vis[maxn];
int a[maxn], b[maxn], c[maxn];
vector<int>V[maxn];
void init()
{
    for(int i = 0; i < maxn; i++)
        V[i].clear();
    for(int i = 1; i <= maxn; i++)
    {
        for(int j = 1; j*i <= maxn; j++)//每个数相应的约数
        {
            V[i*j].push_back(i);//i是哪些数的约数
        }
    }
}
int main()
{
    int n;
    init();
    while(scanf("%d",&n) && n)
    {
        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]] == 0)
                b[i]=a[i];
            else
                b[i]=vis[a[i]];//a[i]的倍数
            for(int j = 0; j < V[a[i]].size(); j++)
                vis[V[a[i]][j]] = a[i];//V[a[i]][j]为a[i]的约数
        }
        memset(vis,0,sizeof(vis));
        for(int i = n; i >= 1; i--)
        {
            if(vis[a[i]] == 0)
                c[i] = a[i];
            else
                c[i] = vis[a[i]];
            for(int j = 0; j < V[a[i]].size(); j++)
                vis[V[a[i]][j]] = a[i];
        }
        LL sum=0;
        for(int i = 1; i <= n; i++)
        {
            sum += (LL)b[i]*(LL)c[i];
        }
        printf("%I64d\n",sum);
    }
    return 0;
}
hdu 4961 Boring Sum(数学题),布布扣,bubuko.com
原文地址:http://blog.csdn.net/u012860063/article/details/38705633