OO’s Sequence
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 83 Accepted Submission(s): 34
Problem Description
OO has got a array A of size n ,defined a function f(l,r) represent the number of i (l<=i<=r) , that there's no j(l<=j<=r,j<>i) satisfy a
i mod a
j=0,now OO want to know
∑i=1n∑j=inf(i,j) mod (109+7).
Input
There are multiple test cases. Please process till EOF.
In each test case:
First line: an integer n(n<=10^5) indicating the size of array
Second line:contain n numbers a i(0<a i<=10000)
In each test case:
First line: an integer n(n<=10^5) indicating the size of array
Second line:contain n numbers a i(0<a i<=10000)
Output
For each tests: ouput a line contain a number ans.
Sample Input
5 1 2 3 4 5
Sample Output
23
Source
求一个每个区间中,满足其他数字%该数字 != 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;
}