5 1 2 3 4 5
23
求一个每个区间中,满足其他数字%该数字 != 0的数字个数,把每个区间满足条件的个数相加
方法:
枚举每个位置,求包含这个数字的区间个数,做加法。
对于ai,看ai左边最近的位置l,al是ai的因数,右边位置r,ar是ai的因数。那么满足的个数就是
(i-l)*(r-i)
预处理所有1-10000的因数。
从左到右,用pre[i]表示数字i出现的i的最右边的位置。算出每个位置的l。
同理从右到左,算出每个位置的r。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; #define maxn 100007 vector<int> head[10007]; int pre[10007]; int num[maxn]; int lef[maxn]; int righ[maxn]; int main(){ int n; for(int i = 1;i <= 10000;i++){ head[i].clear(); for(int j = 1;j*j<=i;j++){ if(i%j == 0){ head[i].push_back(j); head[i].push_back(i/j); } } } while(scanf("%d",&n)!=EOF){ for(int i = 1;i <= n; i++) scanf("%d",&num[i]); memset(pre,0,sizeof(pre)); for(int i = 1;i <= n; i++){ int u = num[i]; int p = 0; for(int j = 0;j < head[u].size(); j++) p = max(p,pre[head[u][j]]); lef[i] = p; pre[u] = i; } memset(pre,0x3f,sizeof(pre)); for(int i = n; i > 0; i--){ int u = num[i]; int p = n+1; for(int j = 0;j < head[u].size();j++) p = min(p,pre[head[u][j]]); righ[i] = p; pre[u] = i; } long long ans = 0,l,r; long long mod = 1000000007; for(int i = 1; i <= n; i++){ ans += (long long)(i-lef[i])*(righ[i]-i); ans %= mod; } cout<<ans<<endl; } return 0; }