一、题目
二、解法
考虑这个条件ai是aj的倍数,且ai/aj是一个质数
,满足这个条件就必须要满足下面两个条件:
-
a
i
a_i
ai是
a
j
a_j
aj的倍数,
好像是废话。 - 设一个数质因数分解后的指数之和为 c n t cnt cnt,则 c n t i = c n t j + 1 cnt_i=cnt_j+1 cnti=cntj+1。
第二个条件很重要,它告诉我们可以把数字的 c n t cnt cnt奇偶划分,就能得到一个二分图,我们就可以想网络流的方面想,图是这样建的:
- 源点连奇数区,边权为 0 0 0,容量为数出现的数量。
- 偶数区连汇点,边权为 0 0 0,容量为数出现的数量。
- 奇数区和偶数区满足条件的数对连接,边权为 c i × c j c_i\times c_j ci×cj,容量为 i n f inf inf。
然后我们在建好的图上跑费用流,由于图是二分图,最长路一定是单调递减的,于是跑费用流是判断费用用大于 0 0 0,这里的费用流写法不同,应写成最大费用最大流。
#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>
#include <cmath>
#define int long long
#define inf (1ll<<60)
const int MAXN = 205;
using namespace std;
int read()
{
int num=0,flag=1;char c;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
while(c>='0'&&c<='9')num=(num<<3)+(num<<1)+(c^48),c=getchar();
return num*flag;
}
int n,tot,S,T,f[MAXN],a[MAXN],b[MAXN],c[MAXN];
int flow[MAXN],dis[MAXN],pre[MAXN],lst[MAXN];
struct edge
{
int v,c,f,next;
}e[MAXN*MAXN];
struct node
{
int u,c;
bool operator < (const node &R) const
{
return c<R.c;
}
};
vector<node> A,B;
void add_edge(int u,int v,int c,int fl)
{
e[++tot]=edge{v,c,fl,f[u]},f[u]=tot;
e[++tot]=edge{u,-c,0,f[v]},f[v]=tot;
}
int dec(int x)
{
int cnt=0,t=sqrt(x);
for(int i=2;i<=t;i++)
while(x%i==0)
{
cnt++;
x/=i;
}
if(x!=1) cnt++;
return cnt;
}
bool pd(int x,int y)
{
if(x%y==0 && dec(x/y)==1) return 1;
if(y%x==0 && dec(y/x)==1) return 1;
return 0;
}
bool bfs()
{
for(int i=S;i<=T;i++)
dis[i]=-inf;
flow[S]=inf;dis[S]=0;pre[S]=-1;
priority_queue<node> q;
q.push(node{S,0});
while(!q.empty())
{
int u=q.top().u,t=q.top().c;
q.pop();
if(dis[u]>t) continue;
for(int i=f[u];i;i=e[i].next)
{
int v=e[i].v,c=e[i].c;
if(dis[v]<dis[u]+c && e[i].f>0)
{
dis[v]=dis[u]+c;
pre[v]=u;
lst[v]=i;
flow[v]=min(flow[u],e[i].f);
q.push(node{v,dis[v]});
}
}
}
return dis[T]!=-inf;
}
int get()
{
int sum=0,cost=0;
while(bfs())
{
if(cost+flow[T]*dis[T]>=0)
{
cost+=flow[T]*dis[T];
sum+=flow[T];
int cur=T;
while(cur^S)
{
e[lst[cur]].f-=flow[T];
e[lst[cur]^1].f+=flow[T];
cur=pre[cur];
}
}
else return sum+cost/(-dis[T]);
}
return sum;
}
signed main()
{
n=read();tot=1;
S=0;T=n+1;
for(int i=1;i<=n;i++)
{
a[i]=read();
if(dec(a[i])%2)
A.push_back(node{i,a[i]});
else
B.push_back(node{i,a[i]});
}
for(int i=1;i<=n;i++)
b[i]=read();
for(int i=1;i<=n;i++)
c[i]=read();
for(int i=0;i<A.size();i++)
add_edge(S,A[i].u,0,b[A[i].u]);
for(int i=0;i<B.size();i++)
add_edge(B[i].u,T,0,b[B[i].u]);
for(int i=0;i<A.size();i++)
for(int j=0;j<B.size();j++)
if(pd(A[i].c,B[j].c))
add_edge(A[i].u,B[j].u,c[A[i].u]*c[B[j].u],inf);
printf("%lld\n",get());
}