ACM-ICPC 2018南京现场赛 J-Prime Game(枚举素因子贡献+欧拉筛)

  • Post author:
  • Post category:其他


题目

å¨è¿éæå¥å¾çæè¿°

思路来源


https://blog.csdn.net/m0_37624640/article/details/83276324

题解

博主代码写的清楚明白

把每个数分解素因子,分别在对应的素因子vector内放入该数的位置

那么,由于一个数不同的素因子不会超过8个(2*3*5*7*11*13*17*19=9 699 690)

那么最后所有vector里的位置的个数总和也不会超过8e6,遍历即可

一个素因子在pos位置,可能产生的贡献在

左端点在[1,pos]取,右端点在[pos,n]取,

可与它相同的素因子再次出现的时候,不妨出现在next位置

右端点[next,n]取没问题,

左端点应该在[pos+1,next]取,而不是[1,next]取,

避免和上一个位置计算重复的部分

故一个素因子的贡献是

第一个出现的位置pos*(n-pos+1)

后面出现的位置(next-pos)*(n-next+1)

求和即可

往这个有位置的素因子里面先塞个0

所有操作就都统一成(next-pos)*(n-next+1)了

心得

这题卡时间卡得很紧

要求欧拉筛(其实素数筛也能过)+枚举不超过平方素因子写得足够标准

开始用遍历筛出来的所有素数的方法去筛果不其然T了,

后来想想1e6以内的素数有约5e4个,而1e3以内的质数只有168个

多乘了个300的系数不T才怪呢……

分解素因子的时候由于出现了就除掉,实际访问的质数也不会到168

估计cal上限那也就不到100叭,乘一下1e6就搞过去了

以后代码要写的规范呐,别整天debug这些没用的…

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
const int maxn=1e6+10;
typedef long long ll;
using namespace std;
int n;
ll prime[maxn],cnt,ans;
bool ok[maxn];
vector<ll>pos[maxn];//放的是各素因数出现的位置 
void init()
{
	for(ll i=2;i<=maxn;++i)
	{
		if(!ok[i])
		{
		  prime[cnt++]=i;
		  pos[i].push_back(0);//统一操作 
	    }
		for(ll j=0;j<cnt;++j)
		{
			if(prime[j]*i>maxn)break;
			ok[prime[j]*i]=1;
			if(i%prime[j]==0)break;
		}
	}
}
void cal(int a,ll x)
{
	for(int i=0;i<cnt;++i)
	{
		if(prime[i]*prime[i]>x)break;//1000以内的质数的复杂度 168 
		if(x%prime[i]==0)
		{
		 pos[prime[i]].push_back(a);
		 while(x%prime[i]==0)x/=prime[i];
	    }
	}
	if(x>1)pos[x].push_back(a);//用平方写 有效降复杂度 
}
int main()
{
	init();
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
	{
		ll x;
		scanf("%lld",&x);
		cal(i,x);
	}
	for(int i=0;i<cnt;++i)//用cnt处理 有效快速 
	{
		ll &p=prime[i],len=pos[p].size();
		if(len<=1)continue;//只有0 
		/*printf("%lld:",i);
		for(int j=0;j<len;++j)
		printf("%d ",pos[i][j]);
		puts("");*/
		//ans+=pos[p][0]*(n-pos[p][0]+1);
		//塞进去一个0 统一操作 
		for(ll j=1;j<len;++j)
		ans+=(pos[p][j]-pos[p][j-1])*(n-pos[p][j]+1);
	}
	printf("%lld\n",ans);
	return 0;
}



版权声明:本文为Code92007原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。