高橋君とカード / Tak and Cards(dp)

Time limit : 2sec / Memory limit : 256MB

Score : 300 points

Problem Statement

Tak has N cards. On the i-th (1iN) 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

  • 1N50
  • 1A50
  • 1xi50
  • N, A, xi are integers.

Partial Score

  • 200 points will be awarded for passing the test set satisfying 1N16.

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

Copy
4 8
7 9 8 9

Sample Output 1

Copy
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

Copy
3 8
6 6 9

Sample Output 2

Copy
0

Sample Input 3

Copy
8 5
3 6 2 8 7 6 5 9

Sample Output 3

Copy
19

Sample Input 4

Copy
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

Copy
8589934591

  • The answer may not fit into a 32-bit integer.

        o#思路转载至、这里#o


题意:给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;
}

猜你喜欢

转载自blog.csdn.net/Du_Mingm/article/details/80385565