AtCoder Beginner Contest 262

D - I Hate Non-integer Number

https://atcoder.jp/contests/abc262/tasks/abc262_d

Time Limit: 2.5 sec / Memory Limit: 1024 MB

Score : 400 points

Problem Statement

You are given a sequence of positive integers A=(a1,,aN) of length N.
There are (2N1) ways to choose one or more terms of A. How many of them have an integer-valued average? Find the count modulo 998244353.

Constraints

  • 1N100
  • 1ai109
  • All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
a1 aN

Output

Print the answer.

Sample Input 1

3
2 6 2

Sample Output 1

6

For each way to choose terms of A, the average is obtained as follows:

  • If just a1 is chosen, the average is a11=21=2, which is an integer.
  • If just a2 is chosen, the average is a21=61=6, which is an integer.
  • If just a3 is chosen, the average is a31=21=2, which is an integer.
  • If a1 and a2 are chosen, the average is a1+a22=2+62=4, which is an integer.
  • If a1 and a3 are chosen, the average is a1+a32=2+22=2, which is an integer.
  • If a2 and a3 are chosen, the average is a2+a32=6+22=4, which is an integer.
  • If a1, a2, and a3 are chosen, the average is a1+a2+a33=2+6+23=103, which is not an integer.

Therefore, 6 ways satisfy the condition.


Sample Input 2

5
5 5 5 5 5

Sample Output 2

31

Regardless of the choice of one or more terms of A, the average equals 5.

我的笔记

这个动态规划比较重要的点就是将不同分母的情况分开讨论,如果分母确定,那么只需要知道余数,就可以进行转移。但如果将不同分母的情况混在一起讨论,那就需要储存不同选法的和,而和的范围非常宽广,不可能使用数组储存下来,因此无法实现。

状态表示

dp[i][j][k]:= 讨论前 i 个数,选择 j 个数时,和的余数为 k 的情况。

状态转移

不选 a[j] 时:dp[j+1][k][l]+=dp[j][k][l]

a[j] 时:dp[j+1][k+1][(l+a[k])%i]+=dp[j][k][l]

代码

#include <bits/stdc++.h>

using namespace std;

const int MOD = 998244353;
const int MAXN = 110;
int N, a[MAXN];
int ans = 0;

int main()
{
    cin >> N;
    for (int i = 0; i < N; i++)
        cin >> a[i];
    for (int i = 1; i <= N; i++) // 分母为i
    {
        vector dp(N + 1, vector(i + 1, vector<int>(i, 0)));
        dp[0][0][0] = 1;
        for (int j = 0; j < N; j++) // 前j+1个数
        {
            for (int k = 0; k <= i; k++) // 选k个数
            {
                for (int l = 0; l < i; l++) // 除i余l
                {
                    dp[j + 1][k][l] += dp[j][k][l];
                    dp[j + 1][k][l] %= MOD;
                    if (k != i)
                    {
                        dp[j + 1][k + 1][(l + a[j]) % i] += dp[j][k][l];
                        dp[j + 1][k + 1][(l + a[j]) % i] %= MOD;
                    }
                }
            }
        }
        ans += dp[N][i][0];
        ans %= MOD;
    }
    cout << ans << endl;
    return 0;
}