正题
题目链接:https://www.luogu.com.cn/problem/P4068
题目大意
nnn种数字,第iii个是aia_iai,有bib_ibi个,价值为ci∗cjc_i*c_jci∗cj
如果一个数字axa_xax和aya_yay配对要求axay\frac{a_x}{a_y}ayax是一个质数且产生cx∗cyc_x*c_ycx∗cy的价值,一个只能配对一次
求在配对价值和不小于000的前提下配对数最多
解题思路
下面那个条件就直接二分+费用流判断即可。
考虑如何建立二分图的条件,满足要求的配对ax,aya_x,a_yax,ay那么就是axa_xax比aya_yay多一个质因数,所以我们按照质因数分解后的质数个数的奇偶性进行二分图即可。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
const ll N=210,inf=1e18;
struct node{ll to,next,w,c;
}a[N*N*3];
ll n,s,t,tot,f[N],mf[N],pre[N];
ll w[N],h[N],b[N],c[N],ls[N],ansc,answ;
bool v[N];queue<int> q;
void addl(ll x,ll y,ll w,ll c){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].w=w;a[tot].c=c;a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot;a[tot].w=0;a[tot].c=-c;return;
}
bool SPFA(){memset(f,0xcf,sizeof(f));q.push(s);f[s]=0;mf[s]=inf;v[s]=1;while(!q.empty()){ll x=q.front();v[x]=0;q.pop();for(ll i=ls[x];i;i=a[i].next){ll y=a[i].to;if(!a[i].w)continue;if(f[x]+a[i].c>f[y]){f[y]=f[x]+a[i].c;mf[y]=min(mf[x],a[i].w);pre[y]=i;if(!v[y])q.push(y),v[y]=1;}}}return f[t]>-inf;
}
void Updata(){ll x=t,w=mf[t];while(x!=s){a[pre[x]].w-=w;a[pre[x]^1].w+=w;x=a[pre[x]^1].to;}answ+=mf[t];ansc+=mf[t]*f[t];return;
}
ll check(ll x){memset(ls,0,sizeof(ls));tot=1;ansc=answ=0;ll S=n+2;addl(s,S,x,0);for(ll i=1;i<=n;i++)if(h[i]&1)addl(S,i,b[i],0);else addl(i,t,b[i],0);for(ll i=1;i<=n;i++)for(ll j=1;j<=n;j++)if(w[i]%w[j]==0&&h[i]==h[j]+1){if(h[i]&1)addl(i,j,inf,c[i]*c[j]);else addl(j,i,inf,c[i]*c[j]);}while(SPFA())Updata();return ansc;
}
int main()
{scanf("%lld",&n);s=0;t=n+1;for(ll i=1;i<=n;i++){ll x;scanf("%lld",&x);w[i]=x;for(ll j=2;j*j<=x;j++)while(x%j==0)x/=j,h[i]++;if(x!=1)h[i]++;}for(ll i=1;i<=n;i++)scanf("%lld",&b[i]);for(ll i=1;i<=n;i++)scanf("%lld",&c[i]);ll l=1,r=n*1e5;while(l<=r){ll mid=(l+r)>>1;if(check(mid)>=0)l=mid+1;else r=mid-1; }check(r);printf("%lld\n",answ);
}