BZOJ1042: [HAOI2008]硬币购物
2016-12-18 10:05
357 查看
Description
硬币购物一共有4种硬币。面值分别为c1,c2,c3,c4。某人去商店买东西,去了tot次。每次带di枚ci硬币,买si的价值的东西。请问每次有多少种付款方法。
Input
第一行 c1,c2,c3,c4,tot 下面tot行 d1,d2,d3,d4,s,其中di,s<=100000,tot<=1000Output
每次的方法数Sample Input
1 2 5 10 23 2 3 1 10
1000 2 2 2 900
Sample Output
427
HINT
Source
dp+容斥预处理dp[i]表示i元钱的方案数(不考虑数量限制)
对于每次询问 答案为dp[S]-第一种超过限制-第二种超过限制-...+第一、二种同时超过限制...+四种同时超过限制
那么怎么求第i种超过限制呢
我们先钦定它用了d[i]+1个 然后总数减掉c[i]*(d[i]+1) 剩下的怎么选都会超过限制了
预处理O(s),每次询问O(16) 数据范围怎么这么小啊
#include <bits/stdc++.h> using namespace std; const int maxn = 100000; int T, c[5] ,d[5], s; long long ans, dp[maxn + 5]; inline void init() { dp[ 0 ] = 1 ; for( int i = 1 ; i <= 4 ; i++ ) for( int j = c[ i ] ; j <= maxn ; j++ ) dp[ j ] += dp[ j - c[ i ] ]; } void dfs(int now, int tot, bool flag) { if( tot < 0 ) return ; if( now == 5 ) { if( flag ) ans -= dp[ tot ]; else ans += dp[ tot ]; return ; } dfs( now + 1, tot - ( d[ now ] + 1 ) * c[ now ] , flag ^ 1 ); dfs( now + 1, tot, flag ); } int main() { for( int i = 1 ; i <= 4 ; i++ ) scanf( "%d", &c[ i ] ); scanf( "%d", &T ); init(); while( T-- ) { ans = 0; for( int i = 1 ; i <= 4 ; i++ ) scanf( "%d", &d[ i ] ); scanf( "%d", &s ); dfs( 1, s, 0 ); printf( "%lld\n", ans ); } return 0; }
相关文章推荐
- BZOJ1042: [HAOI2008]硬币购物
- 【bzoj】1042: [HAOI2008]硬币购物
- [BZOJ 1042][HAOI2008]硬币购物
- [BZOJ1042][HAOI2008]硬币购物-容斥原理
- BZOJ1042: [HAOI2008]硬币购物
- [bzoj]1042: [HAOI2008]硬币购物
- BZOJ1042: [HAOI2008]硬币购物
- 【bzoj1042】【HAOI2008】【硬币购物】【dp+容斥原理】
- BZOJ1042: [HAOI2008]硬币购物
- [bzoj1042][HAOI2008]硬币购物
- 硬币购物 [Codevs1869,Bzoj1042,HAOI2008]
- Bzoj 1042: [HAOI2008]硬币购物 容斥原理,动态规划,背包dp
- bzoj1042[HAOI2008] 硬币购物
- BZOJ 1042 [HAOI2008]硬币购物 - 容斥+DP
- [bzoj1042][HAOI2008][硬币购物] (容斥原理+递推)
- [BZOJ1042][HAOI2008]硬币购物
- bzoj 1042: [HAOI2008]硬币购物
- [BZOJ1042]HAOI2008硬币购物|DP|容斥原理
- BZOJ 1042 HAOI 2008 硬币购物 容斥原理
- bzoj 1042: [HAOI2008]硬币购物【容斥原理+dp】