用二分图建图再跑最大费用最大流就可以了
考场上建图写炸了。。。sad
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const long long INF=1000000000000000ll; int n,en,S,T,h[10005],flag[10005],Back[10005],Tag,tab[100005],cnt,X[10005],Y[10005],xs=0,ys=0; long long A[2005],B[2005],C[2005],D[10005],Cost=0; queue<int> Q; struct Edge{ int b,back,next; long long f,c; }e[2000005]; void AddEdge(int sa,int sb,long long sc,long long sd){ e[++en].b=sb; e[en].back=en+1; e[en].f=sc; e[en].c=sd; e[en].next=h[sa]; h[sa]=en; swap(sa,sb); e[++en].b=sb; e[en].back=en-1; e[en].f=0; e[en].c=-sd; e[en].next=h[sa]; h[sa]=en; } bool SPFA(){ memset(D,-80,sizeof(D)); memset(flag,0,sizeof(flag)); memset(Back,0,sizeof(Back)); D[S]=0; Q.push(S); flag[S]=1; while(!Q.empty()){ int u=Q.front(); Q.pop(); flag[u]=0; for(int i=h[u];i;i=e[i].next){ int v=e[i].b; if(D[u]+e[i].c>D[v] && e[i].f){ D[v]=D[u]+e[i].c; Back[v]=i; if(!flag[v]){ flag[v]=1; Q.push(v); } } } } return D[T]>-INF; } long long Flow(){ long long ans=INF,Co=0; int Tx=Back[T]; while(Tx){ ans=min(ans,e[Tx].f); Co+=e[Tx].c; Tx=Back[e[e[Tx].back].b]; } while(Cost+ans*Co<0)ans--;if(ans<=0){Tag=1;return 0;} Tx=Back[T]; while(Tx){ e[Tx].f-=ans; e[e[Tx].back].f+=ans; Cost+=ans*e[Tx].c; Tx=Back[e[e[Tx].back].b]; } return ans; } long long MaxCost(){ long long ans=0; while(SPFA()){ ans+=Flow(); if(Tag)break; } return ans; } bool Test(int x){ if(x==1 || x==0)return 0; for(int i=2;i*i<=x;i++){ if(x%i==0)return 0; } return 1; } bool Testx(long long x){ if(x==1 || x==0)return 0; for(int i=1;tab[i]*tab[i]<=x && i<=cnt;i++){ if(x%tab[i]==0)return 0; } return 1; } void Prime(){ for(int i=2;i<=40000;i++){ if(Test(i)){tab[++cnt]=i;} } } int Count(long long x){ int px=0; for(int i=1;tab[i]*tab[i]<=x && i<=cnt;i++){ while(x%tab[i]==0){px++;x/=tab[i];} } if(x>1)px++; return px; } int main(){ freopen("4514.in","r",stdin); freopen("4514.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%lld",&A[i]); for(int i=1;i<=n;i++)scanf("%lld",&B[i]); for(int i=1;i<=n;i++)scanf("%lld",&C[i]); Prime(); S=n+1;T=n+2; for(int i=1;i<=n;i++){if(Count(A[i])&1)X[++xs]=i;else Y[++ys]=i;} for(int i=1;i<=xs;i++)AddEdge(S,X[i],B[X[i]],0); for(int i=1;i<=ys;i++)AddEdge(Y[i],T,B[Y[i]],0); for(int i=1;i<=xs;i++){ for(int j=1;j<=ys;j++){ if(A[X[i]]%A[Y[j]]==0 && Testx(A[X[i]]/A[Y[j]])){AddEdge(X[i],Y[j],INF,C[X[i]]*C[Y[j]]);} if(A[Y[j]]%A[X[i]]==0 && Testx(A[Y[j]]/A[X[i]])){AddEdge(X[i],Y[j],INF,C[X[i]]*C[Y[j]]);} } } printf("%lld\n",MaxCost()); return 0; }