显然可以根据质因子个数建二分图,再连源点和汇点,连边就可以跑费用流了。每次跑最大费用,直到费用小于0就结束过程,记录总流量即可 - -
#include"bits/stdc++.h"
using namespace std;
typedef long long ll;
const int N=40005,M=50000;
const int inf=(int)1e9;
const ll llinf=(ll)1e18;
int pri[M+5 >> 2],cnt,flag[M+5];
void Linear_Shaker(){
for(int i=2;i<=M;i++){
if(!flag[i])pri[++cnt]=i;
for(int j=1;pri[j]*i<=M;j++){
flag[pri[j]*i]=1;
if(i%pri[j]==0)break;
}
}
}
int a[N],n,f[N],c[N],color[N],S,T;
struct Edge {
int to;ll cost,flow;
Edge (int _=0,ll __=0,ll ___=0)
{ to=_; flow=__; cost=___;}
} e[N << 1];
int head[N],next[N << 1],tmp=1;
inline void addedge(int fr,int to,ll cost,int flow){
e[++tmp]=Edge(to,flow,cost);next[tmp]=head[fr];head[fr]=tmp;
e[++tmp]=Edge(fr,0,-cost);next[tmp]=head[to];head[to]=tmp;
}
int sep(int x){
int ans=0;if(x<2)return 0;
for(int i=1;pri[i]*pri[i]<=x;i++)
while(x%pri[i]==0)ans++,x/=pri[i];
return ans+(x>1);
}
void init(){
Linear_Shaker();
scanf("%d",&n);int i,j,s,t;S=0,T=n+1;
for(i=1;i<=n;i++)scanf("%d",&a[i]);
for(i=1;i<=n;i++)scanf("%d",&f[i]);
for(i=1;i<=n;i++)scanf("%d",&c[i]);
for(i=1;i<=n;i++)color[i]=sep(a[i]);
for(i=1;i<=n;i++)for(j=i+1;j<=n;j++){
s=i,t=j;if(a[i]<a[j])swap(s,t);
if(a[s]%a[t]==0&&color[s]==color[t]+1){
s=i,t=j;if(color[i]&1)swap(s,t);
addedge(s,t,(ll)c[i]*c[j],inf);
}
}
for(i=1;i<=n;i++)
if(color[i]&1)addedge(i,T,0,f[i]);
else addedge(S,i,0,f[i]);
}
int pre[N],q[N],l,r,inq[N],id[N];
ll dist[N];
bool spfa(){
for(int i=S;i<=T;i++)dist[i]=-llinf,pre[i]=id[i]=0;
dist[S]=0;l=r=1;q[++r]=S;inq[S]=1;
while(l!=r){
l=(l+1)%(n+3);
int s=q[l];inq[s]=0;
for(int i=head[s];i;i=next[i]){
if(e[i].flow>0){
if(dist[s]+e[i].cost>dist[e[i].to]){
dist[e[i].to]=dist[s]+e[i].cost;
pre[e[i].to]=s;id[e[i].to]=i;
if(!inq[e[i].to]){
r=(r+1)%(n+3);
q[r]=e[i].to;
inq[e[i].to]=1;
}
}
}
}
}
return pre[T]!=0;
}
void work(){
ll maxflow=0,i,flow,sumcost=0;
while(spfa()&&sumcost+dist[T]>=0){
flow=inf;
for(i=T;i;i=pre[i])
flow=min(flow,e[id[i]].flow);
if(sumcost+flow*dist[T]<0)
flow=sumcost/(-dist[T]);
for(i=T;i;i=pre[i]){
e[id[i]].flow-=flow;
e[id[i]^1].flow+=flow;
}
maxflow+=flow;
sumcost+=flow*dist[T];
}
printf("%lld\n",maxflow);
}
int main(){
init();work();
return 0;
}