高橋君とカード / Tak and Cards(AtCoder-2037)
Problem Description
Tak has N cards. On the i-th (1≤i≤N) card is written an integer xi. He is selecting one or more cards from these N cards, so that the average of the integers written on the selected cards is exactly A. In how many ways can he make his selection?
Constraints
1≤N≤50
1≤A≤50
1≤xi≤50
N, A, xi are integersPartial Score
200 points will be awarded for passing the test set satisfying 1≤N≤16.
Input
The input is given from Standard Input in the following format:
N A
x1 x2 … xNOutput
Print the number of ways to select cards such that the average of the written integers is exactly A.
Example
Sample Input 1
4 8
7 9 8 9Sample Output 1
5
The following are the 5 ways to select cards such that the average is 8:
Select the 3-rd card.
Select the 1-st and 2-nd cards.
Select the 1-st and 4-th cards.
Select the 1-st, 2-nd and 3-rd cards.
Select the 1-st, 3-rd and 4-th cards.Sample Input 2
3 8
6 6 9Sample Output 2
0
Sample Input 3
8 5
3 6 2 8 7 6 5 9Sample Output 3
19
Sample Input 4
33 3
3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3Sample Output 4
8589934591
The answer may not fit into a 32-bit integer.
题意:有 n 张牌,每张牌有一个整数 xi,现在要在 n 张牌里选 1 或多张,使得所选的牌的平均值是 A,问有多少种选择方式
思路:
由于所给的数据范围不大,因此可设 dp[i][j] 为前 i 张卡上的数相加为 j 的方案数
那么首先枚举 n 件物品,每次考虑使得取得的卡数 i 减少 1 张,那么相应的和的最大值有 j+x[k],因此,对于前 i+1 张卡其相加的值为 j+x[k],那么组成的方案数 dp[i+1][j+x[k]] 就为原本的方案数再加上前 i 张卡的值,即:dp[i+1][j+x[k]]+=dp[i][j]
最后统计方案数即可
Source Program
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#define EPS 1e-9
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define LL long long
const int MOD = 1E9+7;
const int N = 50+5;
const int dx[] = {0,0,-1,1,-1,-1,1,1};
const int dy[] = {-1,1,0,0,-1,1,-1,1};
using namespace std;
int x[N];
LL dp[N][N*N];//dp[i][j]表示前i个数相加值为j的方案数
int main(){
    int n,a;
    scanf("%d%d",&n,&a);
    for(int i=1;i<=n;i++)
        scanf("%d",&x[i]);
    dp[0][0]=1;
    for(int k=1;k<=n;k++){//n个物品
        for(int i=k-1;i>=0;i--){//每次取得的物品个数减少
            for(int j=0;j<=50*i;j++){//统计相加的值,最大为50*i
                dp[i+1][j+x[k]]+=dp[i][j];
            }
        }
    }
    LL res=0;
    for(int i=1;i<=n;i++){
        int val=i*a;//选择i个物品时他们平均值的总和
        res+=dp[i][val];
    }
    printf("%lld\n",res);
    return 0;
}
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号