生活随笔
收集整理的這篇文章主要介紹了
ARC106——E - Medals
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
E - Medals
首先看到這題看不出是一個匹配的題大佬題解
把每一個工人和每一天看成一個二分圖,如果某個工人在某天工作,那么兩者存在邊,現在問題轉化成至少需要多少天,能夠把nnn個工人全部匹配kkk次
顯然天數可以二分,然后問題轉化成判斷1→mid1\to mid1→mid天是否能夠讓工人完全匹配,然后就需要用到霍爾定理。
Hall 定理:二分圖存在最大完備匹配的充要條件是與某一側的任意 kkk 個點相連的另一側的節點 ≥k\ge k≥k個。
按照霍爾定理枚舉每一個集合,假設該集合中我們任意選擇了iii個工人,那么至少有k×ik×ik×i天與之匹配,那么這iii個工人工作天并集的天數≥k×i\ge k×i≥k×i。顯然不容易求iii個工人工作天的并集的天數,于是考慮補集轉化,我們可以求出有哪些天沒有所選工人集合的元素,然后用總天數減去即可。
代碼:
預處理某天有哪些工人能夠工作,狀態壓縮!預處理二進制中1的個數表示選擇的集合有多少人二分中cnt[]數組表示一個桶,cnt[i]表示選擇工人集合是i(i看成一個二進制數)的子集天數和
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std
;
typedef long long ll
;
typedef pair
<int,int> pii
;
const int mod
=1e9+7;
const int N
=19,K
=100010,M
=3*N
*K
;
int work
[M
];
int n
,k
,a
[N
];
int one
[1<<N
],cnt
[1<<N
];
bool check(int mid
)
{memset(cnt
,0,sizeof cnt
);for(int i
=1;i
<=mid
;i
++) cnt
[work
[i
]]++;for(int i
=0;i
<n
;i
++)for(int j
=0;j
<1<<n
;j
++)if(j
>>i
&1) cnt
[j
]+=cnt
[j
^(1<<i
)];for(int i
=0;i
<1<<n
;i
++)if(one
[i
]*k
>mid
-cnt
[(1<<n
)-1-i
]) return 0;return 1;
}
int main()
{IO
;int T
=1;while(T
--){cin
>>n
>>k
;int m
=n
*k
*3;for(int i
=0;i
<n
;i
++) cin
>>a
[i
];for(int i
=0;i
<n
;i
++)for(int j
=1;j
<=m
;j
++)if(((j
-1)/a
[i
]&1)==0) work
[j
]|=1<<i
;for(int i
=1;i
<1<<n
;i
++) one
[i
]=one
[i
>>1]+(i
&1);int l
=n
*k
,r
=m
;while(l
<r
){int mid
=l
+r
>>1;if(check(mid
)) r
=mid
;else l
=mid
+1;}cout
<<l
<<'\n';}return 0;
}
總結:一般求并集的東西都可以考慮補集轉化,求出補集所有子集的個數,然后再用總數減即可。
反思:自己對于集合相關技巧掌握不好~~
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的ARC106——E - Medals的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。