給出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...