NOPI2018 货币系统 bool完全背包 bitset优化转移

NOPI2018 货币系统 bool完全背包 bitset优化转移

题意

给你n种货币的面值,成为A货币系统,让你求出一个货币系统B,使得B系统的货币种类不超过A系统且最小,并且A系统能凑出的面值B系统也能凑出,A系统不能凑出的面值B系统也不能凑出。

[1 leq n leq 100\ a_i leq 25000 ]

分析

当某个货币可以被这个系统中的其他货币表示出来的时候,这个货币就不必存在。

根据这个思路我们发现问题就转化为了bool完全背包。某个货币(x)能够被表示当且仅当(x - k_{a_i})能够被表示

我们用之前bitset刷表的思想,“刷”(x + a_i,x+2a_i...)表示为true,容易发现类似二进制拆分的原理,我们只需要“刷”二的幂次。

所以复杂度又降了一个(log)

我们之所以能刷表,其实是利用了bitset左移仅需要(O(1))时间,把bitset看成桶的话,其实做了一次所有存在的值域的数左移了一部分,因此对于bool背包等问题常常可以用bitset来优化。

代码

const int maxn = 2e5 + 5;

bitset<maxn> st;

int main(){
	int T = rd();
	while(T--){
		st.reset();
		int n = rd();
		vector<int> v(n);
		st[0] = 1;
		for(int i = 0;i < n;i++)
			v[i] = rd();
		sort(v.begin(),v.end());
		int ans = 0;
		for(int i = 0;i < n;i++){
			if(!st.test(v[i])) {
				ans++;
				int x = v[i];
				while(x <= v.back()) {
					st |= st << x;
					x <<= 1;
				}
			}
		}
		printf("%d
",ans);
	}	
}
原文地址:https://www.cnblogs.com/hznumqf/p/14544474.html