BZOJ4514 Sdoi2016 數字配對

2022-05-19 20:52:54 字數 1857 閱讀 2824

給出n種數a[i]和每種數的個數b[i],再給出c[i](1<=i<=n),如果a[i]和a[j]能配對當且僅當a[i]%a[j]==0&&a[i]/a[j]為質數,並且i和j配對的價值為c[i]*c[j],要求在總價值不小於0的情況下,求出最大配對數

跟機房的hanks_o和rose_max討論了老久才做出來

最大費用最大流

首先怎麼處理兩個數是否匹配呢,資料規模太大了,顯然不能直接判質數或者用線性篩存素數

我們發現,因為如果a[i]是a[j]的倍數,所以a[j]的質因數肯定在a[i]的質因數裡面,那麼只要a[i]的質因數減去a[j]的質因數為1時,證明a[i]/a[j]為質數

就用f[i]表示a[i]的質因數個數,可以用o(n*a[i]0.5)做出來

然後就是建邊問題了,最初我們認為因為這並不是二分圖,所以不能直接二分圖轉費用流

但是我們發現,如果a[i]能與a[j]匹配,則i連向j+n(避免重複),流量為無窮大,費用為c[i]*c[j],這時,我們再把j連向i+n,流量為無窮大,費用為c[i]*c[j]

為什麼這麼做?

因為呢,我們在討論的時候發現,一旦i選擇走向j+n的話,j一定也會選擇走向i+n

那麼就記錄總流量,然後總流量/2就是答案了

然而上面的做法會超時,因為流量太大了,普通的費用流(其實是我們平時用的費用流)是一流量一流量的流的,這樣太慢了

那麼我們一旦找到一條增廣路的時候就把這條增廣路的流量榨乾,注意,要判斷總價值是否<0,如果總價值<0就退出費用流

為什麼這樣做是正確的?因為當我們找到這條增廣路的時候,這條增廣路上的總價值一定是最大的(我們找的就是最大的),一旦這條增廣路流不完,那麼說明其他增廣路也肯定不能流

注意要加long long

這次總結了乙個經驗:乙個良好的**習慣是最重要的(就因為平時沒注意,結果硬生生wa了3次)

#include#include

#include

#include

#include

using

namespace

std;

typedef

long

long

ll;struct

node

a[410000];int len,last[410

];void ins(int x,int y,int

c,ll d)

ll d[

410];int pre[410],pos[410

];bool v[410

];int list[410

];int

st,ed;

bool

spfa()}}

head++;if(head==ed+1)head=1

; v[x]=false

; }

return

bk;}

int f[210],a[210],b[210

];ll c[

210];

int zys(int

x) }

if(x!=1) ans++;

return

ans;

}ll ans,t;

void

flow()

}ans+=mc*d[ed];

t+=mc;

for(x=ed;x!=st;x=pos[x])

}}int

main()

st=0;ed=n+n+1

;

for(int i=1;i<=n;i++)

t=0;flow();

printf(

"%lld\n

",t/2ll);

return0;

}

bzoj4514 Sdoi2016 數字配對

有 n 種數字,第 i 種數字是 ai 有 bi 個,權值是 ci。若兩個數字 ai aj 滿足,ai 是 aj 的倍數,且 ai aj 是乙個質數,那麼這兩個數字可以配對,並獲得 ci cj 的價值。乙個數字只能參與一次配對,可以不參與配對。在獲得的價值總和不小於 0 的前提下,求最多進行多少次配...

bzoj4514 Sdoi2016 數字配對

bzoj4514 sdoi2016 數字配對 題意 有 n 種數字,第 i 種數字是 ai 有 bi 個,權值是 ci。若兩個數字 ai aj 滿足ai 是 aj 的倍數且 ai aj 是乙個質數,那麼這兩個數字可以配對,並獲得 ci cj 的價值。乙個數字只能參與一次配對,可以不參與配對。在獲得的...

BZOJ 4514 Sdoi2016 數字配對

time limit 10 sec memory limit 128 mb submit 1606 solved 608 submit status discuss 有 n 種數字,第 i 種數字是 ai 有 bi 個,權值是 ci。若兩個數字 ai aj 滿足,ai 是 aj 的倍數,且 ai a...