给出一个序列A,对于A里面的每个元素,左边最近的能被它整除的元素记为B序列对应位置的,右边最近的是它的整数倍的元素记为C序列对应位置,找不到的记它本身,最后算出对应位置B*C的总和。
容器模拟,按顺序扫一遍,每次如果有符合条件的取出来,即为最近的。最后把它的下标放到对应位置的容器中,然后倒序求一遍,最后求和。
#include <iostream> #include <cmath> #include <cstdio> #include <cstring> #include <vector> #include <iomanip> #include <queue> #include <algorithm> using namespace std; const int maxn=100010; vector<int>p[maxn]; int n; int a[maxn]; int b[maxn]; int c[maxn]; int main() { while(scanf("%d",&n)!=EOF) { if(n==0) { break; } for(int i=0;i<maxn;i++) { p[i].clear(); } memset(b,-1,sizeof(b)); memset(c,-1,sizeof(c)); for(int i=0;i<n;i++) { scanf("%d",&a[i]); } c[n-1]=n-1; p[a[0]].push_back(0); for(int i=1;i<n;i++) { for(int j=1;j<=sqrt(a[i]);j++) { int u=j; if(a[i]%j==0) { for(int k=0;k<p[u].size();k++) { c[p[u][k]]=i; } p[u].clear(); int v=a[i]/j; for(int k=0;k<p[v].size();k++) { c[p[v][k]]=i; } p[v].clear(); } } p[a[i]].push_back(i); } for(int i=0;i<maxn;i++) { p[i].clear(); } b[0]=0; p[a[n-1]].push_back(n-1); for(int i=n-2;i>=0;i--) { for(int j=1;j<=sqrt(a[i]);j++) { int u=j; if(a[i]%j==0) { for(int k=0;k<p[u].size();k++) { b[p[u][k]]=i; } p[u].clear(); int v=a[i]/j; for(int k=0;k<p[v].size();k++) { b[p[v][k]]=i; } p[v].clear(); } } p[a[i]].push_back(i); } for(int i=0;i<n;i++) { if(b[i]==-1) { b[i]=i; } if(c[i]==-1) { c[i]=i; } } long long sum=0; for(int i=0;i<n;i++) { sum+=(long long)a[b[i]]*a[c[i]]; } printf("%I64d\n",sum); } return 0; }
原文地址:http://blog.csdn.net/q295657451/article/details/39530425