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 ai%aj=0 ,now OO want to know Σni=1Σnj=if(i,j) mod (109+7) .
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
ai
(0<
ai
<=10000)
题意
f(l,r) 被定义为满足下列条件的 ai 的个数: l≤i,j≤r , i≠j 且不存在 ai % aj=0 。
求 Σni=1Σnj=if(i,j) mod (109+7)
解题思路
此题可等价的视作:每个 ai 对结果 ans 的贡献,若对于 ai 所能满足的最大区间已知 [l,r] ,则贡献为 (i−l+1)×(r−i+1) 。
在 n 个数中,能使得 ai 满足 ai % aj=0 的 aj 必须是 ai 的约数。
故统计每个值的出现位置,通过大小为 10000 的向量组保存,v[ ai ] 向量保存所有值等于 ai 的数是位置。
对于每个 ai ,枚举其约数,对其所有的约数 aj 出现的位置 j 进行判断:
- 以大于 i 的最小 j 作为 ai 最大区间的右边界
- 以小于 i 的最大 j 作为 ai 最大区间的左边界
代码
#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
const int N = 100000 + 10;
int n, a[N], l[N], r[N];
vector<int> v[10010];
void solve(int x)
{
int val = a[x];
int sqr = sqrt(val + 0.5);
for(int i=1;i<=sqr;i++)
{
if(val % i) continue;
for(int idx = 0, cur = i;idx<2;idx++)
{
for(int j=0;j<v[cur].size();j++)
{
//printf("v[%d][%d] = %d\n", cur, j, v[cur][j]);
if(v[cur][j] < x)
l[x] = max(l[x], v[cur][j]+1);
if(v[cur][j] > x)
r[x] = min(r[x], v[cur][j]-1);
}
cur = val / i;
}
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=10000;i++)
v[i].clear();
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
v[a[i]].push_back(i);
}
long long ans = 0;
for(int i=1;i<=n;i++)
{
l[i] = 1; r[i] = n;
solve(i);
(ans += (long long)(i-l[i]+1)*(r[i]-i+1)%mod) %= mod;
}
printf("%lld\n", ans);
}
}