Gym 101981J 2018南京

现场赛的时候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;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值