[HAOI2008]硬币购物
link
一开始以为是一道智商税题目,结果发现似乎并没有那么简单。这道题给我提供了许多很有价值的思路。
首先多重背包是肯定会死的,二进制拆分似乎也并不是很有用处 (\(O(QN\log N)\)肯定超时),于是想到整体减空白。
整体是什么?显然会是没有限制,也就是所有硬币随便用时的方案数,此时直接暴力完全背包预处理即可。那空白呢?
空白的意义可以认为是强制硬币使用超量的情况。既然强制硬币超量,那么大可以先把超量硬币的面额减去,那么剩下的钱不管怎么花最后整体结果都是不合法的,而后者的计算就转换到了整体部分了,于是解决问题就只差个容斥了。可以枚举1到16,然后1的个数判加减即可,基本容斥。
#include
#define zczc
#define int long long
const int N=100010;
inline void read(int &wh){
wh=0;int f=1;char w=getchar();
while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
wh*=f;return;
}
int m,n,now,ans,num,s[N],a[5],b[5];
signed main(){
#ifdef zczc
freopen("in.txt","r",stdin);
#endif
s[0]=1;
for(int i=1;i<=4;i++){
read(a[i]);
for(int j=a[i];j=0)ans+=((num&1)?-1:1)*s[now];
}
printf("%lld\n",ans);
}
return 0;
}