NOIP模拟 洛阳怀(质因数分解)
传送门
【题目分析】
用正确的做法竟然只有45pts。。。。。好吧完全没想到1e9怎么弄qwq
显然,我们对所有的a[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;
}