http://acm.hdu.edu.cn/showproblem.php?pid=5288
题意:定义f(l,r)为区间中不能整除其余数的数的个数,求增序区间中f的和。直接求肯定T,那么就算每个位置的数对最终答案贡献了多少次,那就找到离他最近的左右两个他能整除的数的位置,ans+=l*r,记录位置,因为数的大小只有1000,所以枚举因子去找就ok了!
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+10;
const ll mod=1e9+7;
int a[maxn];int pos[(int)1e4+10];int n;int l[maxn],r[maxn];
int main(){
while(scanf("%d",&n)!=EOF){
memset(pos,0,sizeof(pos));
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;i++){
int minn=0x7f7f7f7f;
for(int j=1;j<=sqrt(a[i]);j++){
if(a[i]%j==0){
if(pos[j]!=0)minn=min(minn,i-pos[j]);
if(pos[a[i]/j]!=0) minn=min(minn,i-pos[a[i]/j]);
}
}
l[i]=(minn==0x7f7f7f7f)?(i):minn;
pos[a[i]]=i;
}
memset(pos,0,sizeof(pos));
for(int i=n;i>=1;i--){
int minn=0x7f7f7f7f;
for(int j=1;j<=sqrt(a[i]);j++){
if(a[i]%j==0){
if(pos[j]!=0)minn=min(minn,pos[j]-i);
if(pos[a[i]/j]!=0) minn=min(minn,pos[a[i]/j]-i);
}
}
r[i]=(minn==0x7f7f7f7f)?(n+1-i):minn;
pos[a[i]]=i;
}
ll ans=0;
for(int i=1;i<=n;i++){
ans=(ans+((ll)(l[i]*r[i])%mod))%mod;
}
printf("%lld\n",ans);
}
}
如果实现就记录好位置了,也可以用二分去查找最近的位置,用lowerbound和upperbound
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL INF=0x3f3f3f3f;
const LL MAXN=100010;
const LL MOD=1e9+7;
LL N;
LL a[MAXN];
vector<LL> V[10010];
int main(){
freopen("in.txt","r",stdin);
while(scanf("%I64d",&N)!=EOF){
for(LL i=0;i<=10000;i++) V[i].clear();
for(LL i=1;i<=N;i++){
scanf("%I64d",&a[i]);
V[a[i]].push_back(i);
}
for(LL i=0;i<=10000;i++) sort(V[i].begin(),V[i].end());
LL ans=0;
for(LL i=1;i<=N;i++){
LL n=a[i];
LL m=sqrt(n)+1;
LL l=0,r=N+1;
for(LL j=1;j<=m;j++){
if(n%j==0){
if(V[j].size()>0){
LL pos=lower_bound(V[j].begin(),V[j].end(),i)-V[j].begin(),pos2=upper_bound(V[j].begin(),V[j].end(),i)-V[j].begin();
if(pos>0) l=max(l,V[j][pos-1]);
if(pos2<V[j].size()) r=min(r,V[j][pos2]);
}
LL t=n/j;
if(V[t].size()>0){
LL t=n/j;
LL pos=lower_bound(V[t].begin(),V[t].end(),i)-V[t].begin(),pos2=upper_bound(V[t].begin(),V[t].end(),i)-V[t].begin();
if(pos>0) l=max(l,V[t][pos-1]);
if(pos2<V[t].size()) r=min(r,V[t][pos2]);
}
}
}
if(l<i&&r>i) ans=(ans+(r-i)*(i-l))%MOD;
}
printf("%I64d\n",ans);
}
return 0;
}