トップページに戻る    次の競技プログラミングの問題へ    前の競技プログラミングの問題へ

ABC-044-C 高橋君とカード

■■■問題■■■

高橋君は、N枚のカードを持っています。
i(1 <= i <= N)番目のカードには、整数xiが書かれています。

高橋君は、これらのカードの中から1枚以上を選び、
選んだカードに書かれた整数の平均をちょうどAにしたいと考えています。

そのようなカードの選び方が何通りあるか求めてください。

■■■入力■■■

N A
x1 x2 ・・・ xN

●1 <=  N <= 50
●1 <=  A <= 50
●1 <= xi <= 50
●N,A,xi はいずれも整数である

■■■出力■■■

書かれた整数の平均がちょうどAとなるようなカードの選び方の総数を出力せよ。


C#のソース

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static string InputPattern = "InputX";

    static List<string> GetInputList()
    {
        var WillReturn = new List<string>();

        if (InputPattern == "Input1") {
            WillReturn.Add("4 8");
            WillReturn.Add("7 9 8 9");
            //5
            //平均が8となるカードの選び方は、以下の5通りです。
            //●3枚目のカードのみを選ぶ。
            //●1枚目と2枚目のカードを選ぶ。
            //●1枚目と4枚目のカードを選ぶ。
            //●1枚目、2枚目および3枚目のカードを選ぶ。
            //●1枚目、3枚目および4枚目のカードを選ぶ。
        }
        else if (InputPattern == "Input2") {
            WillReturn.Add("3 8");
            WillReturn.Add("6 6 9");
            //0
        }
        else if (InputPattern == "Input3") {
            WillReturn.Add("8 5");
            WillReturn.Add("3 6 2 8 7 6 5 9");
            //19
        }
        else if (InputPattern == "Input4") {
            WillReturn.Add("33 3");
            var sb = new System.Text.StringBuilder();
            for (int I = 1; I <= 33; I++) {
                if (I >= 2) sb.Append(" ");
                sb.Append(3);
            }
            WillReturn.Add(sb.ToString());
            //8589934591
            //答えは32ビット整数型に収まらない場合があります
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    static void Main()
    {
        List<string> InputList = GetInputList();
        int[] wkArr = InputList[0].Split(' ').Select(X => int.Parse(X)).ToArray();
        int A = wkArr[1];
        int[] XArr = InputList[1].Split(' ').Select(X => int.Parse(X)).ToArray();

        //場合の数[枚数,合計]なDP表
        int UB_I = wkArr[0];
        int UB_J = XArr.Sum();
        long[,] DPArr = new long[UB_I + 1, UB_J + 1];
        DPArr[0, 0] = 1;

        foreach (int EachX in XArr) {
            for (int I = UB_I; 0 <= I; I--) {
                for (int J = UB_J; J >= 0; J--) {
                    if (DPArr[I, J] == 0) continue;
                    int NewI = I + 1;
                    int NewJ = J + EachX;
                    DPArr[NewI, NewJ] += DPArr[I, J];
                }
            }
        }

        long AnswerCnt = 0;
        for (int I = 1; I <= UB_I; I++) {
            for (int J = 0; J <= UB_J; J++) {
                if (J == A * I)
                    AnswerCnt += DPArr[I, J];
            }
        }
        Console.WriteLine(AnswerCnt);
    }
}


解説

配るDPで、場合の数[枚数,合計]を更新してます。