A - OO’s Sequence(所有區間內無其他因子的數的和)
阿新 • • 發佈:2018-11-27
原題: https://cn.vjudge.net/problem/HDU-5288
題意:
一個區間的貢獻為:此區間F數的個數
F數滿足:區間內其他位置沒有出現過其因子
解析:
預處理所有數的因子,vector x[i]記錄值為i的數出現在原陣列的下標
對於每個原陣列的數,求出後面第一個其因子出現的位置nex和前面最近的位置pre,那麼這個數對答案的貢獻為:nex-pre-1(以i為端點的區間數量)+(i-pre-1)*(nex-i-1)(前面選一個後面選一個為端點)
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const LL mod =1e9+7;
int a[100000+2];
vector<int>x[10009];
vector<int>fac[10009];
void init(){
for(int i=1;i<=10000;i++){
for(int j=1;j<=sqrt(i)+0.1;j++){
if(i%j==0){
fac[i].push_back(j);
fac[i].push_back(i/j);
}
}
}
}
int main(){init();
int n;
while(cin>>n){
for(int i=1;i<=10000;i++)x[i].clear(),x[i].push_back(0);
for(int i=1;i<=n;i++){
scanf("%d",a+i);
x[a[i]].push_back(i);
}
for(int i=1;i<=10000;i++)x[i].push_back(n+1);
LL ans= 0;
for(int i=1;i<=n;i++){
int maxpre=0,minnex=n+1;
for(int j=0;j<fac[a[i]].size();j++){
//printf("when find %d's fac %d\n",a[i],fac[a[i]][j]);
int c=fac[a[i]][j];
int nex=upper_bound(x[c].begin(),x[c].end(),i)-x[c].begin();
int pre=nex-1;
if(x[c][pre]==i)pre--;
nex=x[c][nex];
pre=x[c][pre];
//printf("pre=%d nex=%d\n",pre,nex);
maxpre=max(maxpre,pre);
minnex=min(minnex,nex);
}
ans=(ans+minnex-maxpre-1+(i-maxpre-1)*(minnex-i-1))%mod;
}
printf("%lld\n",ans);
}
}