[NOIp2018]货币系统 背包

时间:2025-05-02 14:06:43

LG传送门

完全背包板子题

显然就是判断有多少种面值的货币可以被其他面值的货币表示,完全背包搞一搞就好了。

考场代码(一看这两格缩进就知道是考场代码):

#include<cstdio>
#include<cstring>
#include<algorithm>
#define R register
#define I inline
using namespace std;
const int S=110,N=25010;
I int rd(){
R int f=0; R char c=getchar();
while(c<48||c>57) c=getchar();
while(c>47&&c<58) f=f*10+(c^48),c=getchar();
return f;
}
int a[S],f[N];
I int max(int x,int y){return x>y?x:y;}
int main(){
R int T=rd(),n,m,p,i,j,k;
while(T--){
n=rd(),m=0,p=0,memset(f,0,sizeof f),f[0]=1;
for(i=1;i<=n;++i) a[i]=rd(),p=max(p,a[i]);
sort(a+1,a+1+n);
for(i=1,k=1;i<=p;++i){
for(j=1;j<k;++j)
if(f[i-a[j]]){f[i]=1; break;}
if(i==a[k]){
if(f[i]) ++m;
f[a[k]]=1,++k;
}
}
printf("%d\n",n-m);
}
return 0;
}

仔细一看我的考场代码写好像把完全背包板子里面那层循环丢到外面来了,然而跑得飞快,洛谷上测72ms,下面有正常写法394ms。

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define R register
#define I inline
using namespace std;
const int S=110,N=2500010; char buf[S],*p1,*p2;
I char gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,S,stdin),p1==p2)?EOF:*p1++;}
I int rd(){
R int f=0,b=1; R char c=gc();
while((c<48||c>57)&&c!=45) c=gc();
if(c==45) b=0,c=gc();
while(c>47&&c<58) f=(f<<3)+(f<<1)+(c^48),c=gc();
return b?f:~f+1;
} int a[S],f[N];
I int max(int x,int y){return x>y?x:y;}
int main(){
R int T=rd(),n,m,p,i,j;
while(T--){
n=rd(),m=0,p=0,memset(f,0,sizeof f),f[0]=1;
for(i=1;i<=n;++i) a[i]=rd(),p=max(p,a[i]);
sort(a+1,a+1+n);
for(i=1;i<=n;++i){
if(f[a[i]]) ++m;
for(j=a[i];j<=p;++j)
if(f[j-a[i]]) f[j]=1;
}
printf("%d\n",n-m);
}
return 0;
}