题目:
http://acm.hdu.edu.cn/showproblem.php?pid=5288
题意:
给定序列,问对该序列的每个区间,有多少个数字满足,在该区间中,其他数字都不是该数字的因数
思路:
观察数字范围只有10^4,算出每个数字极左因数的位置,极右因数的位置,则该数字贡献为(R-X)(X-L),其中X为该数字在序列中的位置
预处理算出10^4内每个数字的因数,用ys向量存储;
做两次遍历,第一次从左向右,算出每个数字的极左因数位置,从左向右扫的过程用pos记录每个已计算的数字的位置;
第二次从右向左算极右因数位置
题目的ans超过int应用long long计算,同时,在计算中应先把(R-X)化成long long!
代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int MAXSIZE = 100000 + 5;
const int mod = 1e9+7;
vector<int> ys[10005];
int larr[MAXSIZE],rarr[MAXSIZE],arr[MAXSIZE];
int pos[MAXSIZE];
int main(){
for (int i=1;i<=10000;++i){
for (int j=i;j<=10000;j+=i){
ys[j].push_back(i);
}
}
int n;
while (scanf("%d",&n)!=EOF){
memset(arr,0,sizeof(arr));
memset(larr,0,sizeof(larr));
memset(rarr,0,sizeof(rarr));
for (int i=1;i<=n;++i) scanf("%d",&arr[i]);
memset(pos,0,sizeof(pos));
for (int i=1;i<=n;++i){
int t=0;
for (int k=0;k<ys[i].size();++k){
t=max(t,pos[ys[i][k]]);
}
larr[i]=t;
pos[arr[i]]=i;
}
for (int i=1;i<=10000;++i) pos[i] = n+1;
for (int i=n;i>=1;--i){
int t=n+1;
for (int k=0;k<ys[i].size();++k){
t=min(t,pos[ys[i][k]]);
}
rarr[i] = t;
pos[arr[i]]=i;
}
long long ans=0;
for (int i=1;i<=n;++i){
ans+=(long long)(rarr[i]-i)*(i-larr[i])%mod;
ans%=mod;
//cout<<"lr: "<<larr[i]<<" "<<rarr[i]<<endl;
}
cout<<ans<<endl;
}
return 0;
}