OO’s Sequence
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 4190 Accepted Submission(s): 1552
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
51 2 3 4 5
Sample Output
23
题意:原题题意就不说了,实际上就是给n(n<=1e5)个数,对于每一个数,如果存在它左边和右边连续的x,y个数和这个数构成的区间中没有这个数的因子,那么结果就+1,问结果是多少。显然只需要枚举每一个数的因子,然后找它左右两边离它最近的因子即可。a[i]很小(<=10000),预处理每个数因子,然后左右扫一遍记录每个数左右两边离它最近的因子的位置,最后再统计一下即可。别忘了long long和mod。
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=200010;
const ll mo=1e9+7;
int n,m,k;
int a[maxn],sum[maxn];
int c[maxn],pos[maxn],l[maxn],r[maxn];
ll ans,ct,cnt,tmp,flag;
char s[maxn];
vector<int>vc[10010];
void init()
{
for(int i=1;i<=10000;i++)
{
for(int j=1;j*i<=10000;j++)
{
vc[i*j].push_back(i);
}
}
}
int main()
{
init();
while(scanf("%d",&n)!=EOF)
{
ans=0; flag=1;
memset(pos,-1,sizeof(pos));
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
l[i]=0;
for(int j=0;j<vc[a[i]].size();j++)
{
int v=vc[a[i]][j];
l[i]=max(l[i],pos[v]);
}
pos[a[i]]=i;
}
memset(pos,-1,sizeof(pos));
for(int i=n;i>=1;i--)
{
r[i]=n+1;
for(int j=0;j<vc[a[i]].size();j++)
{
int v=vc[a[i]][j];
if(pos[v]!=-1)r[i]=min(r[i],pos[v]);
}
pos[a[i]]=i;
}
ans=0;
for(int i=1;i<=n;i++)
{
ll x=(i-l[i]),y=(r[i]-i);
ans=(ans+(x*y)%mo)%mo;
//cout<<l[i]<<" "<<r[i]<<endl;
}
printf("%lld\n",ans%mo);
// if(flag) puts("YES"); else puts("NO");
}
return 0;
}