题面
这道题我是亲自在考场上考过的
先说题解吧
一个货币系统中
x
x
x是没用的,当且仅当他能被系统中别的货币表示
我们拿
R
M
B
RMB
RMB来举个例子
发现所有的钱都能被一分钱表示出来 所以只留一个一分钱的就好了!
啪
咳咳 不闹了
题面可以简述为:给你一个货币系统
A
A
A 让我们可以给他简化 使得所有可以表示的钱还能表示出来。输出最后简化剩下的货币数量。
我们考虑一个像背包的东西,由于我菜逼的背包技术,我也不知道这是啥背包…反正我能做出来我乐意
每次操作到
a
i
a_i
ai时,考虑能不能被它前面的数字所组成
我们知道如果
x
x
x能被前
i
i
i个数组成且组成
x
x
x的数当中包含
a
i
a_i
ai那么
(
x
−
a
i
)
(x-a_i)
(x−ai)也必然能被前
i
i
i个数来组成
那么我们很容易想到定义
f
(
x
)
f(x)
f(x)表示
x
x
x能否被组成,那么根据上面的想法显然有
f
(
x
)
=
f
(
x
)
∨
f
(
x
−
a
i
)
f(x) = f(x) \vee f(x-a_i)
f(x)=f(x)∨f(x−ai)。
直接上代码
#include<bits/stdc++.h>
using namespace std;
inline void read(int &x){
int s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+(ch&15);ch=getchar();}
x=s*w;
}
int t,n,ans,a[101];
bool vis[30000];
int main(){
read(t);
while(t--){
read(n);ans=n;
for(int i=1;i<=n;i++)read(a[i]);
memset(vis,0,sizeof(vis));
sort(a+1,a+1+n);vis[0]=1;
for(int i=1;i<=n;i++){
if(vis[a[i]])ans--;
for(int j=a[i];j<=a[n];j++)vis[j]=vis[j]|vis[j-a[i]];
}
printf("%d\n",ans);
}
}
这几天要好好复习背包九讲了,别再像去年那样连这种水分都不要…