版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38083668/article/details/82750720
C - 高橋君とカード / Tak and Cards
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
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
扫描二维码关注公众号,回复:
3292517 查看本文章
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.
解析:
平均数不太好处理,我们将问题转化一下。
令表示处理到前个数选了个数和为的方案数,可得状态转移方程:
然后就是滚动数组降掉第一维就行了,具体看代码。
代码:
#include <bits/stdc++.h>
using namespace std;
const int Max=51;
int n,m,now,num[Max],sum[Max];
long long ans;
long long f[3][Max][Max*Max];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&num[i]),sum[i]=sum[i-1]+num[i];
f[1][0][0]=f[0][0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=i;j++)
for(int k=0;k<=sum[i];k++)
{
f[now][j][k]=f[now^1][j][k];
if(k>=num[i]) f[now][j][k]+=f[now^1][j-1][k-num[i]];
}
now^=1;
}
for(int i=1;i<=n;i++) ans+=f[now^1][i][i*m];
cout<<ans<<"\n";
return 0;
}