Time limit : 2sec / Memory limit : 256MB
Score : 300 points
Problem Statement
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 integers.
Partial 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 … xN
Output
Print the number of ways to select cards such that the average of the written integers is exactly A.
Sample Input 1
4 8 7 9 8 9
Sample 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 9
Sample Output 2
0
Sample Input 3
8 5 3 6 2 8 7 6 5 9
Sample 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 3
Sample Output 4
8589934591
- The answer may not fit into a 32-bit integer.
题意:给n个数字,求这n个数字平均数为a的组合数。
思路:第一次打atcoder,这个题目分部分解和完全解两种。部分解要求n<=16,完全解n<=50。
部分解的做法很简单,枚举所有子集,看看是否满足条件即可。
完全解要用背包来做,设dp(i,j,k)为在第i个数字前选j个,和为k的所有组合数目。由于我们知道平均数的计算方法为Σxi/X,设a=Σxi/X,则a*X=Σxi。我们最后只需要统计所有的dp(n,X,a*X)就行了。
转移的话首先计数要把之前的结果转移到当前结果下,dp(i,j,k)+=dp(i-1,j,k)。接下来就是背包了,dp(i,j,k)+=dp(i-1,j-1,k-x(i-1)) | {k >= x(i-1)}
代码是自己敲的
#include <iostream> #include <math.h> typedef long long ll; using namespace std; ll dp[55][55][2551]; int main() { int x[2550],n,a,i,j,k; cin>>n>>a; for(i=0;i<n;i++)cin>>x[i]; dp[0][0][0]=1; for(i=1;i<=n;i++) { for(j=i;j>=0;j--) { for(k=a*n+1;k>=0;k--) { dp[i][j][k]+=dp[i-1][j][k]; if(k>=x[i-1] && j>=1) dp[i][j][k]+=dp[i-1][j-1][k-x[i-1]]; } } } ll ans=0; for(i=1;i<=n;i++)ans+=(dp[n][i][i*a]); cout<<ans<<endl; return 0; }