洛谷P1450 [HAOI2008]硬幣購物
阿新 • • 發佈:2017-08-02
opened define printf 容斥原理 view 兩種 背包 請問 string
題目描述
硬幣購物一共有4種硬幣。面值分別為c1,c2,c3,c4。某人去商店買東西,去了tot次。每次帶di枚ci硬幣,買si的價值的東西。請問每次有多少種付款方法。
輸入輸出格式
輸入格式:
第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s
輸出格式:
每次的方法數
輸入輸出樣例
輸入樣例#1:1 2 5 10 2 3 2 3 1 10 1000 2 2 2 900輸出樣例#1:
4 27
說明
di,s<=100000
tot<=1000
[HAOI2008]
這道題是道數論題 首先我們可以沒有限制地像完全背包一樣求出f【i】
f【i】表示硬幣合起來是 i 的方案數
然後利用容斥原理 用總的方案數減去不合法的方案數就好啦
用遞歸實現代碼比較簡潔
類似於
總的方案數 -一種超的方案數和+兩種超的方案數和-三種超的方案數和~~~~~~~~~
具體的容斥原理百度學學咯?
#include<cstdio> #include<cstring> #include<algorithm> #define LL long long using namespace std; LL read(){ LL ans=0,f=1,c=getchar(); while(c<‘0‘||c>‘9‘){if(c==‘-‘) f=-1View Code; c=getchar();} while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();} return ans*f; } LL s,c[5],d[5],T; LL ans,f[100007]; void rc(int i,int s,int k){ if(i==5){ ans+=f[s]*k; return ; } rc(i+1,s,k); if((LL)c[i]*(d[i]+1)<=s) rc(i+1,s-(c[i]*(d[i]+1)),-k); }int main() { c[1]=read(); c[2]=read(); c[3]=read(); c[4]=read(); T=read(); f[0]=1; for(int i=1;i<=4;i++) for(int j=c[i];j<=100000;j++) f[j]+=f[j-c[i]]; while(T--){ d[1]=read(); d[2]=read(); d[3]=read(); d[4]=read(); s=read(); ans=0; rc(1,s,1); printf("%lld\n",ans); } return 0; }
洛谷P1450 [HAOI2008]硬幣購物