題意:定義一個函數f(l,r) = i的個數使得在區間[l,r]中不存在a[i]%a[j]=0。∑i=1..n∑j=i..n f(i,j) mod (10^9+7)。
解析:通過枚舉因子,從前到後再從後到前求出能包含i的區間的左右端點的邊界,即可。
[code]:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1e5+5;
const LL MOD = 1e9+7;
int n,a[maxn],b[maxn];
int l[maxn],r[maxn];
void sol(){
int i,j;
memset(b,0,sizeof(b));
for(i = 1;i <= n;i++){
l[i] = 0;
for(j=1;j*j<=a[i];j++){
if(a[i]%j) continue;
l[i] = max(l[i],max(b[a[i]/j],b[j]));
}
b[a[i]] = i;
}
memset(b,63,sizeof(b));
for(i = n;i >= 1;i--){
r[i] = n+1;
for(j=1;j*j<=a[i];j++){
if(a[i]%j) continue;
r[i] = min(r[i],min(b[a[i]/j],b[j]));
}
b[a[i]] = i;
}
LL res = 0;
for(i = 1;i <= n;i++){
res += (1LL*i-1LL*l[i])*(1LL*r[i]-1LL*i);
res %= MOD;
}
printf("%lld\n",(res+MOD)%MOD);
}
int main(){
int i,j;
while(~scanf("%d",&n)){
for(i = 1;i <= n;i++) scanf("%d",&a[i]);
sol();
}
return 0;
}