OO’s Sequence
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 4011 Accepted Submission(s): 1484
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
Author
FZUACM
Source
题意:某区间的贡献为其区间内有多少个数,不能被区间内其他数整除,问所有子区间的贡献和。
思路:计算出每个数左边和右边最近的能被它整除的数位置,乘起来即可。
# include <iostream>
# include <cstdio>
# include <vector>
# include <algorithm>
using namespace std;
const int maxn = 1e5+3;
typedef long long LL;
const LL mod = 1e9+7;
int a[maxn], l[maxn], r[maxn];
vector<int>v[maxn];
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=1; i<=n; ++i) scanf("%d",&a[i]),l[i]=0;
for(int i=1; i<=n; ++i) v[a[i]].push_back(i);
for(int i=1; i<=n; ++i)
{
r[i] = n+1;
for(int j=1; j<=(int)sqrt(a[i]); ++j)
{
if(a[i] % j == 0)
{
for(int k=j,t=2;t;k=a[i]/k,--t)
{
if(v[k].size())
{
int p = lower_bound(v[k].begin(), v[k].end(), i)-v[k].begin();
if(p) l[i] = max(l[i], v[k][p-1]);
if(p != v[k].size() && !(p==v[k].size()-1 && v[k][p]==i))
{
if(v[k][p] == i) ++p;
r[i] = min(r[i], v[k][p]);
}
}
}
}
}
}
LL ans = 0;
for(int i=1; i<=n; ++i)
{
v[a[i]].clear();
ans = (ans + (i-l[i])*(r[i]-i)%mod)%mod;
}
printf("%I64d\n",ans);
}
return 0;
}