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

Time limit : 2sec / Memory limit : 256MB

Score : 300 points

Problem Statement

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

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 
#include 
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>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<

你可能感兴趣的:(规律题(找啊,找啊,找不着啊),思维(抖啊,抖啊,抖个机灵儿))