日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

4514: [Sdoi2016]数字配对

發布時間:2023/11/27 生活经验 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 4514: [Sdoi2016]数字配对 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Description

有 n 種數字,第 i 種數字是 ai、有 bi 個,權值是 ci。

若兩個數字 ai、aj 滿足,ai 是 aj 的倍數,且 ai/aj 是一個質數,

那么這兩個數字可以配對,并獲得 ci×cj 的價值。

一個數字只能參與一次配對,可以不參與配對。

在獲得的價值總和不小于 0 的前提下,求最多進行多少次配對。


對于滿足條件的\(a_i/a_j\)一定要滿足\(a_i\)的質因子個數比\(a_j\)大一

所以可以對于每個數的質因子個數建二分圖,只有異側才有連邊

至于總價值不小于0,在總價值<0的時候停止就行了


#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#include<algorithm>
#define M 1000001
#define LL long long 
using namespace std;LL t,n,m,k,a[M],b[M],c[M],edge[M],nex[M],head[M],ver[M],cnt=1,h[M],d[M],cs[M],inq[M],cur[M],w[M],e[M],ed,zz,ans;
queue <LL> q;
void add(LL x,LL y,LL z,LL co)
{ver[++cnt]=y; nex[cnt]=head[x]; head[x]=cnt; edge[cnt]=z; cs[cnt]=co;ver[++cnt]=x; nex[cnt]=head[y]; head[y]=cnt; edge[cnt]=0; cs[cnt]=-co;
}bool spfa()
{memset(d,0,sizeof(d));memcpy(cur, head, sizeof(head));while(q.size()) q.pop();memset(h,-0x3f,sizeof(h));q.push(0); d[0]=1; h[0]=0; while(q.size()){LL x=q.front(); q.pop(); inq[x]=0;for(LL i=head[x];i;i=nex[i])if(edge[i] && h[ver[i]]<h[x]+cs[i]){h[ver[i]]=h[x]+cs[i]; d[ver[i]]=d[x]+1; if(!inq[ver[i]]) q.push(ver[i]);inq[ver[i]]=1;}}if(d[t]) return 1;return 0;
}LL dinic(LL x,LL flow)
{if(!flow || x==t) return flow;LL re=flow, k;for(LL & i=cur[x];i && re;i=nex[i])if(edge[i] && h[ver[i]]==h[x]+cs[i] && d[ver[i]]==d[x]+1){k=dinic(ver[i],min(re, edge[i]));re-=k; edge[i]-=k; edge[i^1]+=k;}return flow-re;
}LL fj(LL x)
{if(x==1) return 0;LL k=sqrt(x),ans=0; k+=1;for(LL i=2;i<=k;i++) if(x%i==0) while(x%i==0) x/=i,ans+=1;if(x!=1) ans+=1;return ans;
}int main()
{scanf("%lld",&n); t=n+1;for(LL i=1;i<=n;i++) scanf("%lld",&a[i]);for(LL i=1;i<=n;i++) scanf("%lld",&b[i]);for(LL i=1;i<=n;i++) scanf("%lld",&c[i]);for(LL i=1;i<=n;i++) w[i]=fj(a[i]);for(LL i=1;i<=n;i++) if(w[i]%2)for(LL j=1;j<=n;j++) if(w[j]%2==0 && ((a[i]%a[j]==0 && w[i]==w[j]+1)||(a[j]%a[i]==0 && w[j]==w[i]+1)))add(i,j,0x3f3f3f3f,c[i]*c[j]);for(LL i=1;i<=n;i++) if(w[i]%2) add(0,i,b[i],0);else add(i,t,b[i],0);while(spfa()){bool bll=1;while(k=dinic(0,0x3f3f3f3f)) {if(ed+h[t]*k<0) {ans+=ed/(-h[t]); bll=0; break;}ed+=h[t]*k, ans+=k;}if(!bll) break;}printf("%lld",ans);
}

轉載于:https://www.cnblogs.com/ZUTTER/p/10253589.html

總結

以上是生活随笔為你收集整理的4514: [Sdoi2016]数字配对的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。