货币系统(完全背包求方案数+思维)

货币系统

题目分析

给出一组序列a1…an 让你找出另外一组序列b1…bm使得序列a中能够表示的所有数序列b同样能够表示出来。让你求出序列b最小需要多少个元素。

首先分析一个性质:bi一定属于序列a中元素
反证法:假设bi不属于序列a,bi可以被序列a中元素表示出来,然而序列a中元素又可以通过序列b表示出来,那么bi可以被自己所在的序列b表示出来,则bi一定不属于序列b (序列b一定最简),所以bi一定属于序列a

序列b中元素一定不能相互表示

那么我们只需要在序列a中找到不能够被其他元素表示的ai就可以的出序列b
利用完全背包求出每个数字j能够被表示的方案数,最后统计方案数为1的j即为b序列中元素。

#include<bits/stdc++.h>
#define ll long long

using namespace std;
const int maxn=2e5+10;

int n,m,ans;

ll f[maxn];
int a[maxn];




int main() {


	int T;
	cin>>T;
	while(T--) {
		cin>>n;
		for(int i=1; i<=n; i++) {
			cin>>a[i];
			m=max(m,a[i]);
		}
		memset(f,0,sizeof(f));
        f[0]=1;
		for(int i=1; i<=n; i++) {//完全背包求方案数 
			for(int j=a[i]; j<=m; j++) { 
                 f[j]+=f[j-a[i]];//f(i,j)=f(i-1,j)+f(i,j-a[i]); 
			}
		}
		ans=0;
		for(int i=1;i<=n;i++){//统计那些数字不能被其他数字表示 
			if(f[a[i]]==1)ans++;
		}
		cout<<ans<<endl;
	}



	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值