NOIP模拟 洛阳怀(质因数分解)

传送门

【题目分析】

用正确的做法竟然只有45pts。。。。。好吧完全没想到1e9怎么弄qwq

显然,我们对所有的a[i]进行质因数分解,得到a[i]=\prod_{i=1}^{k}p_{i}^{q_{i}},根据定义式,如果pi为“好质数”,那么会做出qi的贡献,否则做出-qi的贡献,用这个办法就可以计算出一个数的贡献。

考虑前缀gcd单降不增,那么我们从最后一个向前扫,如果前缀gcd产生了正的贡献,显然是不减更优,反之减去。

最后统计一下答案就行了(或者统计初始答案然后进行修改)

【代码~】

#include<bits/stdc++.h>
#include<tr1/unordered_map>
using namespace std;
const int MAXP=1e5+10;
const int MAXN=2e3+10;

int n,m,ans;
int a[MAXN],bad[MAXN];
int gc[MAXN];
bitset<MAXP> prime;
int pri[MAXP],cnt;
tr1::unordered_map<int,int> isbad;

int Read()
{
	int i=0,f=1;
	char c;
	for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
	if(c=='-')
	  f=-1,c=getchar();
	for(;c>='0'&&c<='9';c=getchar())
	  i=(i<<3)+(i<<1)+c-'0';
	return i*f;
}

int gcd(int a,int b)
{
	return a%b?gcd(b,a%b):b;
}

void pre()
{
	prime[1]=1;
	for(int i=2;i<=MAXP;++i)
	{
		if(!prime[i])
		  pri[++cnt]=i;
		for(int j=1;j<=cnt&&pri[j]*i<=MAXP;++j)
		{
			pri[i*pri[j]]=1;
			if(i%pri[j]==0)
			  break;
		}
	}
}

int judge(int x)
{
	if(x==1)
	  return 0;
	int score=0;
	for(int i=1;i<=cnt&&pri[i]*pri[i]<=x;++i)
	{
		if(x%pri[i]==0)
		{
			if(isbad[pri[i]])
			{
				while(x&&x%pri[i]==0)
				  score--,x/=pri[i];
			}
			else
			{
				while(x&&x%pri[i]==0)
				  score++,x/=pri[i];
			}
		}
	}
	if(x!=1)
	{
		if(isbad[x])
		  score--;
		else
		  score++;
	}
	return score;
}

int main()
{
	pre();
	n=Read(),m=Read();
	for(int i=1;i<=n;++i)
	  a[i]=Read();
	for(int i=1;i<=m;++i)
	  bad[i]=Read(),isbad[bad[i]]=1;
	for(int i=1;i<=n;++i)
	  ans+=judge(a[i]);
	gc[1]=a[1];
	for(int i=2;i<=n;++i)
	  gc[i]=gcd(gc[i-1],a[i]);
	int now=1;
	for(int i=n;i>=1;--i)
	{
		gc[i]/=now;
		int sco=judge(gc[i]);
		if(sco<0)
		{
			ans-=sco*i;
			now*=gc[i];
		}
	}
	cout<<ans;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/g21glf/article/details/83449457
今日推荐