现场赛的时候qt一下就过了这题。。。
然后今年我想了挺久的。。。计数还是太菜了
我们对于每一个质数考虑,看有多少个区间,这个质数是存在的。
那么其实就是所有的区间数量减去没有这个质数区间的数量
对于一段连续的没有这个质数的区间长度为len,那么这一段中没有这个质数的区间的数量为len*(len+1)/2.
先线性筛素数,记录最小质因子,那么我们对每一个ai进行nlogn的质因数分解,分解出一个因数p就把当前的坐标加入vector[p]中
这样vector中最多存了nlogn个数字,而计算没有这个质数的区间的数量也是计算nlogn次。
当时qt好像是正向求,没有用去总区间数减去没有的区间数,比这个还麻烦一些。
#include<bits/stdc++.h>
#define maxl 1000010
using namespace std;
int n;
int a[maxl],p[maxl],dy[maxl];
long long v[maxl];
bool no[maxl];
vector <int> f[maxl];
long long ans;
inline void shai()
{
no[1]=true;
int t,j;
for(int i=2;i<maxl;i++)
{
if(!no[i]) p[++p[0]]=i,dy[i]=i;
j=1,t=i*p[1];
while(j<=p[0] && t<maxl)
{
dy[t]=p[j];
no[t]=true;
if(i%p[j]==0)
break;
t=i*p[++j];
}
}
}
inline void prework()
{
for(int i=1;i<=p[0];i++)
f[p[i]].clear();
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
int x=a[i],last=0;
while(x>1)
{
if(dy[x]!=last)
f[dy[x]].push_back(i);
last=dy[x];
x/=dy[x];
}
}
}
inline void mainwork()
{
ans=0;int l,r,len;
long long tmp;
for(int i=1;i<=p[0];i++)
if(f[p[i]].size()>0)
{
tmp=v[n];
l=1;r=0;len=f[p[i]].size();
if(f[p[i]][0]>1)
tmp-=v[f[p[i]][0]-1];
for(int j=0;j<len-1;j++)
if(f[p[i]][j+1]>f[p[i]][j]+1)
{
l=f[p[i]][j]+1;r=f[p[i]][j+1]-1;
tmp-=v[r-l+1];
}
if(f[p[i]][len-1]<n)
tmp-=v[n-f[p[i]][len-1]];
ans+=tmp;
}
}
inline void print()
{
printf("%lld\n",ans);
}
int main()
{
shai();
for(long long i=1;i<maxl;i++)
v[i]=i*(i+1)/2;
while(~scanf("%d",&n))
{
prework();
mainwork();
print();
}
return 0;
}