程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 硬幣購物,硬幣錯印釘子上

硬幣購物,硬幣錯印釘子上

編輯:C++入門知識

硬幣購物,硬幣錯印釘子上


2016.1.27

 

 

試題描述

現在一共有4種硬幣,面值各不相同,分別為ci(i=1,2,3,4)。某人去商店買東西,去了tot次,每次帶di枚ci硬幣,購買價值為si的貨物。請問每次有多少種付款方法。

輸入 第一行包括五個數,分別為c1,c2,c3,c4和tot 接下來有tot行,每行五個數,第i+1行五個數依次為第i次購物所帶四種硬幣的數目和購買貨物的價值(d1,d2,d3,d4,s )。各行的數兩兩之間用一個空格分隔。 輸出 一行,包括tot個數,依次為每次付款的方法數。兩數之間用一個空格分隔。 輸入示例 1 2 5 10 2
3 2 3 1 10
1000 2 2 2 900 輸出示例 4 27 其他說明 數據范圍:0<di,s<=100000,0<tot<=1000,數據面值最大不超過20,所給數據保證每次至少有一種付款方法。

 

hzwer給的容斥原理解法

先預處理出達到面值s的方法,不考慮硬幣是否超過限制。這個用簡單背包就好。

然後從裡面扣出有至少一枚硬幣超過限制的方法即是答案。

又有:至少一枚硬幣超限=第一種硬幣超限+第二種硬幣超限+第三種硬幣超限+第四種硬幣超限-第一種和第二種都超限-第一種和第三種都超限-第一種和第四種都超限-第二種和第三種都超限-第二種和第四種都超限-第三種和第四種都超限+......-四種都超限

然後就狀壓容斥

若第一種硬幣超限,則f[s-(d[1]+1)*c[1]]即為方案數,因為保證了多用一次第一種硬幣。以此類推

注意判sum超s的情況

 

AC代碼:

#include<iostream> using namespace std; int c[5],tot,d[5],s,ct,sum,flag; long long f[100005],ans; int main() { for(int i=1;i<=4;i++) scanf("%d",&c[i]); scanf("%d",&tot); 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(tot--) { for(int i=1;i<=4;i++) scanf("%d",&d[i]); scanf("%d",&s); ans=0; for(int i = (1 << 4) - 1 ; i >= 0 ; i-- ) { ct=0;sum=0; for(int j = 3 ; j >= 0 ; j-- ) { if(1<<j & i) ct++,sum+=(d[j+1]+1)*c[j+1]; } if(s<sum) continue; if(ct & 1) ans-=f[s-sum]; else ans+=f[s-sum]; } if(flag) cout<<" "; flag=1; cout<<ans; } } View Code

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved