ICPC Arab Collegiate Programming Contest 2014 C Feast Coins 【01背包+枚举】

Description

Last feast the young princess received way too many coins. Since she is very young, she doesn’t know thevalue of each coin, if you give her a coin with the value 5 or a coin with the value 1, she will considerthem both as just 1 coin, regardless of the value. 

However, she can notice that the coin with value 5 doesn’t look the same as the coin with value 1, andshe will be happy if she has the same number of coins of each value. Otherwise, she will not be happy.She has a lot of coins of different values, and she needs some subset of these coins such that the sum oftheir values should be exactly S, and the number of coins of each value in this subset should be the same.Can you help her to count the number of different ways to do this?

Input

Your program will be tested on one or more test cases. The first line of the input will be a single integerT (1 ≤ T ≤ 100) representing the number of test cases. Followed by T test cases. Each test case startswith a line containing two integers separated by a single space S and N (1 ≤ ≤ 5,000) (1 ≤ N ≤ 50)representing the total required sum and the number of different values of coins, respectively. Followed byN lines, each one will contain two integers separated by a single space Vi and Ci (1 ≤ ViCi ≤ 5,000)representing the value of a coin and the number of coins the princess has with this value, respectively. Foreach test case, all values of Vi will be distinct.  

Output

For each test case print a single line containing “Case n:” (without quotes) where n is the test case number(starting from 1) followed by a space then the number of different ways to make the total sum asdescribed above. Two ways are considered different if any coin value does not appear the same number oftimes in both ways. 

You can assume that the result will always fit in a 64-bit signed integer.

样例输入

2
10 2
2 2
6 1
10 4
1 10
2 10
3 10
4 10 

样例输出

Case 1: 0
Case 2: 5 

样例解释

In the first test case, the only way to make the sum 10, is to use the following subset of coins (2, 2, 6),but this isn’t valid because there are 2 coins with value 2 and 1 coin with value 6. 

In the second test case, the following are the 5 different ways: (1, 1, 1, 1, 1, 1, 1, 1, 1, 1), (2, 2, 2, 2, 2),(2, 2, 3, 3), (1, 1, 4, 4), (1, 2, 3, 4). 

题目大意: 

有T种硬币,每种硬币值Vi,个数是Ci,问多少种选择的方案使得总价钱是S,而且每种硬币选中个数一样。

分析:

注意到选出的每种硬币的个数一定是一样的,那么可以枚举硬币的个数 x ,并且由于硬币的面值是整数,所以 x 一定是 S 的因子。

确定了 x 之后,则题目转变为:

有T种硬币,每种硬币值Vi,问多少种选择的方案使得总价钱是 S/x 。

每个硬币有两种选择,拿或不拿,那么这就是一个01背包问题,转移方程为 dp[j] += dp[j-val[i]] 。

具体解释见代码。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define INF 0x3f3f3f3f
#define mst(a,num) memset(a,num,sizeof a)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define repd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef long long ll;
typedef pair PII;
typedef pair PLL;
typedef vector VI;
const ll mod = 1e9 + 7;
const int maxn = 5000 + 5;

int val[maxn],cnt[maxn];
int mxcnt,sumval;
ll dp[maxn][maxn];

int main() {
    int t;
    scanf("%d",&t);
    rep(cas,1,t){
        int S,n;
        scanf("%d%d",&S,&n);
        mxcnt=0;
        sumval=0;
        rep(i,1,n){
            scanf("%d%d",val+i,cnt+i);
            mxcnt=max(mxcnt,cnt[i]);
            sumval+=val[i];
        }
        mst(dp,0);
        rep(c,1,mxcnt){
            if(sumval*c

 

你可能感兴趣的:(ACM学习,动态规划)