1. 程式人生 > >[NOIp2018]貨幣系統

[NOIp2018]貨幣系統

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;
}