Codeforces 856C [DP]

来源:互联网 发布:福建网络服务公司 编辑:程序博客网 时间:2024/05/20 14:19

Description

给定n个数,求将这n个数按一定顺序拼在一起是11的倍数的方案数。

Solution

11的倍数的奇数位之和与偶数位之和之差为11的倍数。
把每个数记为奇数位之和与偶数位之和之差,那么如果他的第一位是奇数位,就相当于加上这个数,否则就是减掉这个数。
先考虑长度为奇数的数,可以O(n2)DP出有i个数第一位是奇数位,贡献为j的方案数fi,j
在考虑把偶数插进去。
直接插就好了。
也是O(n2)的DP吧。。

#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>using namespace std;const int MOD = 998244353;const int N = 2020;typedef long long ll;inline char get(void) {    static char buf[100000], *S = buf, *T = buf;    if (S == T) {        T = (S = buf) + fread(buf, 1, 100000, stdin);        if (S == T) return EOF;    }    return *S++;}inline void read(int &x) {    static char c; x = 0;    for (c = get(); c < '0' || c > '9'; c = get());    for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';}inline int readi(int &x) {    static char c; x = 0; int cnt = 1;    for (c = get(); c < '0' || c > '9'; c = get());    for (; c >= '0' && c <= '9'; c = get()) {        x += (c - '0') * cnt; cnt *= -1;    }    x = (x % 11 + 11) % 11;    return cnt;}int n, x, l1, l2, res, test;int a[N], b[N], c[N];int dp[N][12], dp1[N][12];int ans;inline int Mod(int x, int P) {    return (x % P + P) % P;}inline int Min(int a, int b) {    return a < b ? a : b;}int main(void) {    read(test);    while (test--) {        read(n); ans = 0; *c = *b = 0;        for (int i = 1; i <= n; i++) {            x = readi(a[i]);            if (~x) c[++*c] = a[i];            else b[++*b] = a[i];        }        l1 = (*b + 1) / 2; l2 = *b / 2;        memset(dp, 0, sizeof dp);        dp[0][0] = 1;        for (int i = 1; i <= *b; i++) {            for (int j = 0; j <= n; j++)                for (int k = 0; k < 11; k++) {                    dp1[j][k] = dp[j][k];                    dp[j][k] = 0;                }            for (int j = 0; j <= n; j++)                for (int k = 0; k < 11; k++) {                    if (j) dp[j][k] += (ll)dp1[j - 1][Mod(k - b[i], 11)] * (l1 - j + 1) % MOD;                    dp[j][k] += (ll)dp1[j][Mod(k + b[i], 11)] * (l2 - i + j + 1) % MOD;                    dp[j][k] %= MOD;                }        }        for (int j = 0; j < l1; j++)            for (int k = 0; k < 11; k++)                dp[j][k] = 0;        for (int i = 1; i <= *c; i++) {            for (int j = 0; j <= n; j++)                for (int k = 0; k < 11; k++) {                    dp1[j][k] = dp[j][k];                    dp[j][k] = 0;                }            for (int j = 0; j <= n; j++)                for (int k = 0; k < 11; k++) {                    if (j) dp[j][k] += (ll)dp1[j - 1][Mod(k + c[i], 11)] * (j - 1) % MOD;                    dp[j][k] += (ll)dp1[j][Mod(k - c[i], 11)] * (i - j + *b) % MOD;                    dp[j][k] %= MOD;                }        }        for (int i = 0; i <= n; i++)            ans = Mod(ans + dp[i][0], MOD);        cout << ans << endl;    }    return 0;}
原创粉丝点击