传送门
唉我觉得这题数据范围1e5都能做啊。。。
居然只出了2000
考完听
z
x
y
zxy
zxy说我的贪心可以卡但过了?
可能今天本来是
0
+
10
+
0
0+10+0
0+10+0只是运气好
T
1
T1
T1骗了
100
p
t
s
100pts
100pts吧233.
下面讲讲贪心:
令
w
i
=
∏
i
=
1
k
p
i
a
i
w_i=\prod_{i=1}^kp_i^{a_i}
wi=∏i=1kpiai
令
A
=
∑
a
i
p
i
是
好
质
数
,
B
=
∑
a
i
,
p
i
是
坏
质
数
A=\sum_{a_i} p_i是好质数,B=\sum_{a_i},p_i是坏质数
A=∑aipi是好质数,B=∑ai,pi是坏质数
那么
f
i
=
A
−
B
f_i=A-B
fi=A−B
令
g
i
=
g
c
d
(
w
1
,
w
2
,
.
.
.
,
w
i
)
g_i=gcd(w_1,w_2,...,w_i)
gi=gcd(w1,w2,...,wi)
考虑
j
<
i
j<i
j<i
有
g
i
∣
g
j
g_i|g_j
gi∣gj
令
k
=
g
j
g
i
k=\frac {g_j} {g_i}
k=gigj
那么有
f
g
j
=
f
k
+
f
g
i
f_{g_j}=f_k+f_{g_i}
fgj=fk+fgi
所以如果先在
i
i
i那个地方进行一次操作,无论怎么样都不会令结果变小。
于是我们从后向前算出所有有正的贡献的
i
i
i加到答案里面就行了。
代码:
#include<bits/stdc++.h>
#include<tr1/unordered_map>
using namespace std;
const int N=32005;
int n,m,pri[N],a[5005],b[5005],tot=0,sum=0,ans=0;
bool vis[N];
tr1::unordered_map<int,int>S;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
inline void init(){
for(int i=2;i<=N-5;++i){
if(!vis[i])pri[++tot]=i;
for(int j=1;j<=tot&&i*pri[j]<=N-5;++j){
int k=i*pri[j];
vis[k]=1;
if(i%pri[j]==0)break;
}
}
}
inline int calc(int x){
int ret=0;
for(int i=1;i<=tot&&pri[i]*pri[i]<=x;++i){
if(x==1)break;
if(x!=x/pri[i]*pri[i])continue;
int cnt=0;
while(x==x/pri[i]*pri[i])++cnt,x/=pri[i];
if(S[pri[i]])ret-=cnt;
else ret+=cnt;
}
if(x^1){
if(S[x])--ret;
else ++ret;
}
return ret;
}
int main(){
init();
n=read(),m=read(),S.clear();
for(int i=1;i<=n;++i)a[i]=read();
for(int i=1;i<=m;++i)S[read()]=1;
for(int i=1;i<=n;++i){
sum+=calc(a[i]);
if(i^1)a[i]=__gcd(a[i],a[i-1]);
b[i]=-calc(a[i]);
}
int pos=n,delta=0;
while(pos){
if(b[pos]-delta>0)sum+=(b[pos]-delta)*pos,delta+=b[pos]-delta;
--pos;
}
cout<<sum;
return 0;
}