戳一戳
感覺自己調了半天然後模板打錯了。。。好難過。rsduheiutfhnesrfnsjkenfkj
不bibi了我們講一下如何建圖。我們可以發現這2個數字之間的關係是雙向的。那我們怎麼辦呢~~(手動滑稽 )這裡有乙個很神奇的結論:如果a為b的因數且b除以a的值為質數,那麼將a與b質因數分解後a與b的指數差為1。
其實證明很簡單,若使除出來的值為質數,那首先a肯定將b的所有質因子個數-1全部包含,而最後的乙個質因子也肯定只能差乙個,差多個那麼除出來的值會是最後乙個質因子的幾次方。
那我們就好建圖了。求出所有數的質因數分解出的指數和,若指數和差1且整除就可連邊。
最後,題目寫的並不是求最大費用最大流,我們需要轉化一下。詳見**。
#include
#include
#include
#include
#include
#define int long long
typedef
long
long ll;
using
namespace std;
const
int n =
5002
, m =
900002
, lim = long_long_max >>1;
ll val[m]
;bool vis[n]
;int tot[n]
, a[n]
, b[n]
, c[n]
, prep[n]
, pree[n]
, dis[n]
, s, t, n, cnt, flow[m]
, to[m]
, head[n]
, nxt[m]
;inline
intread()
while
(isdigit
(s))
return x * f;
}inline
void
print
(ll x)
if(x >9)
print
(x /10)
;putchar
(x %10+
'0');}
inline
intmin
(const
int x,
const
int y)
inline
void
addedge
(const
int u,
const
int v,
const
int w,
const ll val)
inline
bool
spfa()
}}}return
~prep[t];}
inline
intdiv
(int x)}if
(x >1)
++ res;
return res;
}inline
intjdz
(const
int x)
ll ek()
if(ans +
1ll* maxflow * dis[t]
<0)
//此時dis[t]為負,我們盡量讓它多跑幾個流,下面是複雜些的寫法。至於為什麼不用判斷lim,是因為太大就除沒了。
ans +
=1ll
* maxflow * dis[t]
; sumflow +
= maxflow;
}/*if(dis[t] != -lim)
while(ans + dis[t] >= 0) */
return sumflow;
}signed
main()
for(
int i =
1; i <= n;
++ i)
b[i]
=read()
;for
(int i =
1; i <= n;
++ i)
c[i]
=read()
;for
(int i =
1; i <= n;
++ i)
addedge
(s, i, b[i],0
);for(
int j =
1; j <= n;
++ j)
}print(ek
());
putchar
('\n');
return0;
}
bye~~ SDOI2016 數字配對
傳送門 裸費用流。建邊 對於a i a j pr ime a j a i frac prime a j a i a j a i prim e a j a i 需要i ii向j n j nj n連,並且j jj向i n i ni n連。費用即為c i c j c i c j c i c j 流量無窮大...
SDOI2016 數字配對
點此看題 考慮這個條件ai是aj的倍數,且ai aj是乙個質數,滿足這個條件就必須要滿足下面兩個條件 第二個條件很重要,它告訴我們可以把數字的cnt cntcn t奇偶劃分,就能得到乙個二分圖,我們就可以想網路流的方面想,圖是這樣建的 然後我們在建好的圖上跑費用流,由於圖是二分圖,最長路一定是單調遞...
SDOI 2016 數字配對
題目鏈結 演算法 記cnti表示第i個數的質因子次數之和 那麼i與j可以配對當且僅當 cnti cntj 1且ai為aj的倍數或cntj cnti 1且aj為ai的倍數 那麼cnti為奇數與cnti為偶數的點構成了兩個集合 考慮費用流 將源點與cnti為奇數的點連一條容量為bi 費用為0的邊 將cn...