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.
又是无限接近正解而没有写出来,原本想着维护一个[1,i)中是a[i]点倍数点下标点最值,但是两个最值都要维护,就不会了。。。
先正着扫一遍,维护[1,i)中是a[i]点倍数点下标点最大值,并及时更新b[i];再倒着扫一遍,维护(i,n]中是a[i]点倍数点下标点最小值,并及时更新c[i]
最后相乘得出答案
#include <cstdio> #include <cstring> #include <vector> using namespace std; const int MAXN=100005; int n,f,g; int a[MAXN],b[MAXN],c[MAXN],indx[MAXN]; long long ans; vector<int> factor[MAXN];//factor[i]表示i点因子的表 int main() { for(int j=1;j<=MAXN;++j) for(int i=j;i<=MAXN;i+=j) factor[i].push_back(j); while(scanf("%d",&n),n!=0) { memset(indx,0,sizeof(indx)); for(int i=1;i<=n;++i) {//indx[x]表示[1,i)中是a[i]的倍数的最大下标 scanf("%d",a+i); f=indx[a[i]]==0?i:indx[a[i]]; b[i]=a[f]; for(int j=0;j<factor[a[i]].size();++j) indx[factor[a[i]][j]]=max(indx[factor[a[i]][j]],i); } memset(indx,0x3f,sizeof(indx)); for(int i=n;i>0;--i) {//indx[x]表示(i,n]中是a[i]的倍数的最小下标 g=indx[a[i]]==0x3f3f3f3f?i:indx[a[i]]; c[i]=a[g]; for(int j=0;j<factor[a[i]].size();++j) indx[factor[a[i]][j]]=min(indx[factor[a[i]][j]],i); } ans=0; for(int i=1;i<=n;++i) ans+=(long long)b[i]*c[i]; printf("%I64d\n",ans); } return 0; }