[ABC262D] I Hate Non-integer Number 题解

[ABC262D] I Hate Non-integer Number Solution

更好的阅读体验戳此进入

题面

已知一个长度为 \(N\) 的数列 \(a_1,a_2,\cdots a_N\),从数列中选出至少一个数,使选出的数平均数为整数,求有多少种这样的方案。

Solution

经典DP,考虑设状态 $ dp(i, j, p, k) $,表示考虑前 $ i $ 个数里选 $ j $ 个的和模 $ p $ 余 $ k $。

转移显然,即:

\[dp(i, j, p, k) \rightarrow dp(i + 1, j, p, k) \]

\[dp(i, j, p, k) \rightarrow dp(i + 1, j + 1, p, (k + a_{i + 1}) \bmod{p}) \]

最终答案即为 $ \sum_{i = 1}^n dp(N, i, i, 0) $。

然后需要注意转移过程中存在 $ j = 0 $,但答案不可以 $ j = 0 $,原因显然。

初始值即为 $ dp(1, 0, i, 0) = 1, dp(1, 1, i, a_1 \bmod{i}) = 1 $。

发现空间无法支持,故可以将 $ i $ 维滚动掉。

Code

#define _USE_MATH_DEFINES
#include <bits/stdc++.h>

#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW(arr) void* Edge::operator new(size_t){static Edge* P = arr; return P++;}

using namespace std;

mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}

typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;

#define MOD (998244353ll)

template < typename T = int >
inline T read(void);

int N;
ll a[110];
ll dp[2][110][110][110];
ll ans(0);

int main(){
    N = read();
    for(int i = 1; i <= N; ++i)a[i] = read();
    for(int i = 1; i <= N; ++i)dp[1][0][i][0] = 1, dp[1][1][i][a[1] % i] = 1;
    for(int i = 1; i < N; ++i){
        for(int j = 0; j <= 100; ++j)for(int p = 0; p <= 100; ++p)for(int k = 0; k <= 100; ++k)dp[!(i & 1)][j][p][k] = 0;
        for(int j = 0; j <= i; ++j)
            for(int p = 1; p <= N; ++p)
                for(int k = 0; k < p; ++k)
                    (dp[!(i & 1)][j][p][k] += dp[i & 1][j][p][k]) %= MOD,
                    (dp[!(i & 1)][j + 1][p][(k + a[i + 1]) % p] += dp[i & 1][j][p][k]) %= MOD;
    }
    for(int i = 1; i <= N; ++i)(ans += dp[N & 1][i][i][0]) %= MOD;
    printf("%lld\n", ans);
    fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
    return 0;
}

template < typename T >
inline T read(void){
    T ret(0);
    int flag(1);
    char c = getchar();
    while(c != '-' && !isdigit(c))c = getchar();
    if(c == '-')flag = -1, c = getchar();
    while(isdigit(c)){
        ret *= 10;
        ret += int(c - '0');
        c = getchar();
    }
    ret *= flag;
    return ret;
}

UPD

update-2023_01_07 初稿

posted @ 2023-02-15 18:46  Tsawke  阅读(45)  评论(0)    收藏  举报