http://acm.hdu.edu.cn/showproblem.php?pid=4961
给定ai数组;
构造bi, k=max(j | 0<j<i,a j%ai=0), bi=ak;
构造ci, k=min(j | i<j≤n,aj%ai=0), ci=ak;
求所有bi∗ci的和
f[x]表示能整除x的最近的下标,边构造边更新f数组,复杂度约为O(N*sqrt(A[I])) = O(10^7),可以接受,然后把所有b*c加起来即可
另外,我写的程序里面c[i]指的是上面说的b[i]...
预先处理好所有ai的因子也许能更快
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <vector> #include <string> #include <cmath> using namespace std; #define N 100005 #define M 16000005 #define pi acos(-1.0) #define eps 1e-9 #define Mod 1000000007 int n , m , K; int a[N]; int f[N]; int c[N]; void work(){ int i , j , k , x , y , d; for (i=0;i<n;++i) scanf("%d",&a[i]); memset(f,-1,sizeof(f)); for (i=0;i<n;++i){ c[i] = ~f[a[i]] ? a[f[a[i]]] : a[i]; x = sqrt(a[i]); for (j=1;j<=x;++j) if (a[i] % j == 0) f[j] = i , f[a[i]/j] = i; } memset(f,-1,sizeof(f)); long long ans = 0; for (i=n-1;i>=0;--i){ ans += 1ll*c[i] * (~f[a[i]] ? a[f[a[i]]] : a[i]); x = sqrt(a[i]); for (j=1;j<=x;++j) if (a[i] % j == 0) f[j] = i , f[a[i]/j] = i; } printf("%I64d\n",ans); } int main(){ while (~scanf("%d",&n) && n) work(); return 0; }