http://acm.hdu.edu.cn/showproblem.php?pid=4961
先贴个O(nsqrtn)求1-n所有数的所有约数的代码:
vector<int>divs[MAXN];
void caldivs()
{
for(int i=1;i<MAXN;i++)
for(int j=i;j<MAXN;j+=i)
divs[j].push_back(i);
}
有了这个当时理下思路就可写了,但是重复数处理注意:
1、用一个数组vis[] vis[i]=1表示i存在 或者pos[v]=j表示v在下标为j的位置 这种方法,虽然高效,但是如果出现重复的数,pos就只是更新到最近的一个数,而且vis只是记录了一个数,最好vis[i]++,如果删除一个数vis[i]--;
处理了重复数281ms AC
100000这个范围的数,即使多CASE,nsqrtn的算法还是可以一搞的
奇怪的是C++显示stack_overflow G++ AC 可是我没有递归啊,难道vector
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <map>
#include <set>
#include <queue>
using namespace std;
#define ls(rt) rt*2
#define rs(rt) rt*2+1
#define ll long long
#define ull unsigned long long
#define rep(i,s,e) for(int i=s;i<e;i++)
#define repe(i,s,e) for(int i=s;i<=e;i++)
#define CL(a,b) memset(a,b,sizeof(a))
#define IN(s) freopen(s,"r",stdin)
#define OUT(s) freopen(s,"w",stdout)
const ll ll_INF = ((ull)(-1))>>1;
const int MAXN = 1e5+10;
const int INF = MAXN*13;///
int vis[MAXN];
int a[MAXN],b[MAXN],c[MAXN];
int maxm[MAXN],minm[MAXN],f[MAXN],g[MAXN],maxpos[MAXN],minpos[MAXN];
vector<int>divs[MAXN];
void caldivs()
{
for(int i=1;i<MAXN;i++)
for(int j=i;j<MAXN;j+=i)
divs[j].push_back(i);
}
int n;
ll ans;
int main()
{
//IN("1002.txt");
caldivs();
while(~scanf("%d",&n) && n)
{
vector<int>pos[MAXN];
CL(vis,0);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
vis[a[i]]++;
pos[a[i]].push_back(i);
maxm[i]=-INF;//
minm[i]=INF;//
}
for(int i=0;i<n;i++)
for(int j=0;j<divs[a[i]].size();j++)
{
int vv = divs[a[i]][j];
if(vis[vv])
{
for(int k=0;k<pos[vv].size();k++)
{
if(i<pos[vv][k])
maxm[pos[vv][k]]=max(maxm[pos[vv][k]],i);
if(i>pos[vv][k])
minm[pos[vv][k]]=min(minm[pos[vv][k]],i);
}
}
}
/*for(int i=0;i<n;i++)
{
for(int j=0;j<divs[a[i]].size();j++)
{
if(vis[divs[a[i]][j]] && maxpos[a[i]]<pos[divs[a[i]][j]])
{
maxm[divs[a[i]][j]]=max( maxm[divs[a[i]][j]],maxpos[a[i]] );
}
if(vis[divs[a[i]][j]] && minpos[a[i]]>pos[divs[a[i]][j]] )
{
minm[divs[a[i]][j]]=min( minm[divs[a[i]][j]],minpos[a[i]] );
}
//printf("%d %d ma=%d mi=%d \n",divs[a[i]][j],a[i],maxm[9],minm[9]);
/
}
}*/
ans=0;
for(int i=0;i<n;i++)
{
if(maxm[i]==-INF)
{
f[i]=maxm[i]=i;//maxm相当于f
}
else
{
f[i]=maxm[i];
}
b[i]=a[f[i]];
if(minm[i]==INF)
{
g[i]=minm[i]=i;//minm相当于g
}
else
{
g[i]=minm[i];
}
c[i]=a[g[i]];
ans+=(long long)b[i]*c[i];
}
/*for(int i=0;i<n;i++)
{
printf("###ma=%d mi=%d\n",f[i],g[i]);
}*/
//
printf("%I64d\n",ans);
}
return 0;
}