题目链接: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