1. 程式人生 > >A - OO’s Sequence(所有區間內無其他因子的數的和)

A - OO’s Sequence(所有區間內無其他因子的數的和)

原題: 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); } }