cf Educational Codeforces Round 141 D. Different Arrays

D. Different Arrays
time limit per test
2 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

You are given an array a consisting of n integers.

You have to perform the sequence of n−2 operations on this array:

during the first operation, you either add a 2 a_2 a2 to a 1 a_1 a1 and subtract a 2 a_2 a2 from a 3 a_3 a3, or add a 2 a_2 a2 to a 3 a_3 a3 and subtract a 2 a_2 a2 from a 1 a_1 a1;
during the second operation, you either add a 3 a_3 a3 to a 2 a_2 a2 and subtract a 3 a_3 a3 from a 4 a_4 a4, or add a 3 a_3 a3 to a 4 a_4 a4 and subtract a 3 a_3 a3 from a 2 a_2 a2;

during the last operation, you either add a n − 1 a_{n−1} an1 to a n − 2 a_{n−2} an2 and subtract a n − 1 a_{n−1} an1 from a n a_n an, or add a n − 1 a_{n−1} an1 to an and subtract a n − 1 a_{n−1} an1 from a n − 2 a_{n−2} an2.

So, during the i-th operation, you add the value of a i + 1 a_{i+1} ai+1 to one of its neighbors, and subtract it from the other neighbor.

For example, if you have the array [1,2,3,4,5], one of the possible sequences of operations is: subtract 2 from a 3 a_3 a3 and add it to a 1 a_1 a1, so the array becomes [3,2,1,4,5];
subtract 1 from a 2 a_2 a2 and add it to a 4 a_4 a4, so the array becomes [3,1,1,5,5];
subtract 5 from a 3 a_3 a3 and add it to a 5 a_5 a5, so the array becomes [3,1,−4,5,10];
So, the resulting array is [3,1,−4,5,10].
An array is reachable if it can be obtained by performing the aforementioned sequence of operations on a. You have to calculate the number of reachable arrays, and print it modulo 998244353.

Input
The first line contains one integer n (3≤n≤300).

The second line contains n integers a1,a2,…,an (0≤ai≤300).
Output

Print one integer — the number of reachable arrays. Since the answer can be very large, print its remainder modulo 998244353.

Examples
Input
4
1 1 1 1

Output
3

Input
5
1 2 3 5 0

Output
7

中文:
给你n个数,用 a i a_i ai表示,执行n-2次操作。
第一次操作有两种选择, a 1 + = a 2 , a 3 − = a 2 a_1 += a_2,a_3 -= a_2 a1+=a2,a3=a2或者 a 1 − = a 2 , a 3 + = a 2 a_1 -= a_2,a_3 += a_2 a1=a2,a3+=a2
第二次操作同样, a 2 + = a 3 , a 4 − = a 3 a_2 += a_3,a_4 -= a_3 a2+=a3,a4=a3或者 a 2 − = a 3 , a 4 + = a 3 a_2 -= a_3,a_4 += a_3 a2=a3,a4+=a3
第n-2此操作为, a n − 2 + = a n − 1 , a n − = a n − 1 a_{n-2} += a_{n-1},a_n -= a_{n-1} an2+=an1,an=an1或者 a n − 2 − = a n − 1 , a n + = a n − 1 a_{n-2} -= a_{n-1},a_n += a_{n-1} an2=an1,an+=an1
最后问你这n个数组成的序列有多少中变化。结果mod上一个大质数。

代码:

#include <bits/stdc++.h>
using namespace std;
 
typedef long long ll;
const int maxn = 300 + 5;
const int mod = 998244353;
const int N = maxn * maxn;
int a[maxn];
int dp[maxn][2 * N + 1];
int n;
 
int main() {
    ios::sync_with_stdio(false);
    while (cin >> n) {
        memset(dp, 0, sizeof(dp));
        memset(a, 0, sizeof(a));
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
        }
        dp[2][a[2] + N] = 1;
        for (int i = 3; i <= n; i++) {
            for (int j = -N; j <= N; j++) {
                dp[i][a[i] + j + N] = (dp[i][a[i] + j + N] + dp[i - 1][j + N]) % mod;
                if (j) {
                    dp[i][a[i] - j + N] = (dp[i][a[i] - j + N] + dp[i - 1][j + N]) % mod;
                }
            }
        }
        int ans = 0;
        for (int i = 0; i <= N * 2; i++) {
            ans = (ans + dp[n][i]) % mod;
        }
        cout << ans << endl;
    }
    return 0;
}

解答:

这里参考官方题解中的解释,官方题解写的非常详细。
第i次操作, a i + = a i + 1 , a i + 2 − = a i + 1 a_i += a_{i+1},a_{i+2} -= a_{i+1} ai+=ai+1,ai+2=ai+1或者 a i − = a i + 1 , a i + 2 + = a i + 1 a_i -= a_{i+1},a_{i+2} += a_{i+1} ai=ai+1,ai+2+=ai+1
首先注意到数据 a i a_i ai的范围是[0, 300],这明显是可以通过记录数据值来作为状态。
此外要注意到,第i此操作后,[1,i-1]个数是不变的,而且不影响i+3及其之后的数。
这里使用dp来考虑,设置状态 d p [ i ] [ x ] [ y ] dp[i][x][y] dp[i][x][y],表示第i次操作时 a i + 1 a_{i+1} ai+1为x, a i + 2 a_{i+2} ai+2为y时有多少种前缀的数量,经过第i次操作后, a i + 3 a_{i+3} ai+3及其之后的序列值就是原始的序列值,没有变化, a i a_{i} ai以及之前的值不会再发生变化。所以仅关注 a i + 1 a_{i+1} ai+1 a i + 2 a_{i+2} ai+2即可。

状态转移方程比较好想,执行第i+1次操作时,会对 a i + 1 , a i + 3 a_{i+1},a_{i+3} ai+1,ai+3产生影响。
如果第i+1次操作是 a i + 1 + = a i + 2 , a i + 3 − = a i + 2 a_{i+1} += a_{i+2},a_{i+3} -= a_{i+2} ai+1+=ai+2,ai+3=ai+2,那么状态转移为:
d p [ i + 1 ] [ y ] [ a i + 3 − y ] dp[i+1][y][a_{i+3} - y] dp[i+1][y][ai+3y] 这里很明显,第i次操作时的 a i + 2 a_{i+2} ai+2对应的值,变成了相对于第i+1次操的" a i + 1 a_{i+1} ai+1",即y;同理相对于第i+1次操作的" a i + 2 a_{i+2} ai+2“ ,及 a i + 3 a_{i+3} ai+3这时对应的操作就是减去y。

如果第i+1次操作是 a i + 1 − = a i + 2 , a i + 3 + = a i + 2 a_{i+1} -= a_{i+2},a_{i+3} += a_{i+2} ai+1=ai+2,ai+3+=ai+2,那么状态转移为:
d p [ i + 1 ] [ y ] [ a i + 3 + y ] dp[i+1][y][a_{i+3} + y] dp[i+1][y][ai+3+y]

注意,如果y等于0的时候,上面的两种操作对应的状态相同,属于重复运算了,需要判断。

以上状态会导致超时,注意到 a i + 1 a_{i+1} ai+1维度不会对状态转移产生影响,可以直接去掉。

考虑第i+1次操作,对 a i + 2 a_{i+2} ai+2有影响,状态转移为:
d p [ i + 1 ] [ a i + 1 + j ] + = d p [ i ] [ j ] dp[i+1][a_{i+1}+j] += dp[i][j] dp[i+1][ai+1+j]+=dp[i][j] 这里注意 d p [ i ] [ j ] dp[i][j] dp[i][j]中的j即为 a i + 2 a_{i+2} ai+2的可能范围
同理
d p [ i + 1 ] [ a i + 1 − j ] + = d p [ i ] [ j ] dp[i+1][a_{i+1}-j] += dp[i][j] dp[i+1][ai+1j]+=dp[i][j]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值