共有 4 种硬币,面值分别为 c1,c2,c3,c4。
某人去商店买东西,去了 n 次。
对于每次购买,他带了 di 枚 i 种硬币,想购买 s 的价值的东西。
请问每次有多少种付款方法。
数据范围:1<=ci,di,s<=1e5,n<=1000
洛谷题解
只有4种数,可以枚举哪些是超过数量上限的
先用不限制次数的做完全背包,然后枚举超过数量上限的集合做容斥
容斥某个集合时,先将一定会引起超限的量取出来,
这样剩下的任意取也会超限,统计与其对应的超限的方案
复杂度:
没有个数限制的背包即完全背包,先做完全背包
有了di的限制之后,考虑把来自>di的转移给撤销掉,回答完询问之后再加回来
完全背包本质上是对若干个位置做了dp的前缀和,而有个数限制时,相当于前缀和作差
复杂度:
量级上比较极限,但是因为背包转移常数较小,所以可以通过
- #include
- using namespace std;
- const int N=1e5+10;
- typedef long long ll;
- int c[4],d[4],s,n;
- ll dp[N];
- int main(){
- dp[0]=1;
- for(int i=0;i<4;++i){
- scanf("%d",&c[i]);
- for(int j=c[i];j
- dp[j]+=dp[j-c[i]];
- }
- }
- scanf("%d",&n);
- while(n--){
- for(int i=0;i<4;++i){
- scanf("%d",&d[i]);
- }
- scanf("%d",&s);
- int up=1<<4;
- ll ans=0;
- for(int i=0;i
- int cnt=0,now=s;
- for(int j=0;j<4;++j){
- if(i>>j&1){
- cnt++;
- now-=c[j]*(d[j]+1);
- }
- }
- if(now<0)continue;
- if(cnt&1)ans-=dp[now];
- else ans+=dp[now];
- }
- printf("%lld\n",ans);
- }
- return 0;
- }
代码2
- #include
- using namespace std;
- const int N=1e5+10;
- typedef long long ll;
- int c[4],d[4],s,n;
- ll dp[N];
- int main(){
- dp[0]=1;
- for(int i=0;i<4;++i){
- scanf("%d",&c[i]);
- for(int j=c[i];j
- dp[j]+=dp[j-c[i]];
- }
- }
- scanf("%d",&n);
- while(n--){
- for(int i=0;i<4;++i){
- scanf("%d",&d[i]);
- int w=c[i]*(d[i]+1);
- for(int j=N-1;j>=w;--j){
- dp[j]-=dp[j-w];
- }
- }
- scanf("%d",&s);
- printf("%lld\n",dp[s]);
- for(int i=0;i<4;++i){
- int w=c[i]*(d[i]+1);
- for(int j=w;j
- dp[j]+=dp[j-w];
- }
- }
- }
- return 0;
- }
-
相关阅读:
找不到mfc140u.dll怎么办?修复缺失mfc140u.dll的多种方案分享
fmllr--学习笔记
9.14小米笔试C++
服务端Skynet(二)——消息调度机制
【华为OD机试真题 python】 太阳能板最大面积【2022 Q4 | 100分】
MySQL (十四) 两阶段提交
ECC加密算法的数学原理
《C++标准库第2版》3.2 虽旧犹新的语言特性 笔记
【Token】JWT使用Token进行登录
操作系统导论--受限制的直接执行
-
原文地址:https://blog.csdn.net/Code92007/article/details/105999966