[题解] 不同的数列
题目
题目内容
我们有一个长度无穷的数列\(a[i]\),其中初始的时候只有数列前n项可能不为0,从第n+1项开始都为0。
我们可以做如下操作任意次。
选择一个\(i\)满足\(a[i]>0\)且\(a[i+1]>0\), 然后将\(a[i]\)减\(1\),\(a[i+1]\)减\(1\),\(a[i+2]\)加\(1\)。
我们现在想要知道,通过任意次做这个操作,能得到多少种不同的数列。
两个数列不同当且仅当这两个数列存在一个对应位置上的数不同。
答案非常大,输出答案对\(1000000007\)取模。
(注意这个不同数列的个数要包括初始的数列,可通过样例2理解)
输入格式
第一行一个整数n。
第二行n个整数,第i个整数代表a[i]。
输出格式
输出一行一个整数表示方案数对1000000007取模的结果。
数据范围
\(n\le 50,0\le a[i]\le 50\)
分析
状态设计
考虑最最最最最暴力的dp状态设计,\(dp[a_i][a_{i+1}]...[a_j]\)表示对于数列\({a_i,a_{i+1},...,a_{j-1},a_j,0,0,0,...}\)的答案。
发现\(dp[a_i][a_{i+1}][a_{i+2}][a_{i+3}]...[a_j]\)可以转移到\(dp[a_i-k][a_{i+1}-k][a_{i+2}+k][a_{i+3}]...[a_j]\)。
其中,从\(a_{i+3}\)到\(a_j\)都没有变化,且为原数列\(a\)中连续的一段数,于是考虑优化。
用\(dp[x][y][z][k]\)表示对于数列\({x,y,z,a_{k},a_{k+1},...,a_{n-1},a_{n},0,0,0,...}\)的答案。
状态转移方程和边界条件
边界条件:
if(x>y) dp[x][y][z][k]=dp[y][y][z][k]若\(x>y\),每次\(x-1,y-1,z+1\),直到\(y=0\),此时\(x\)的值对答案没有影响。下面讨论中默认\(x\le y\)if(k>n) dp[x][y][z][k]=dp[x][y][z][n+1]对于任意的\(k\),\(k>n\),\(dp[x][y][z][k]\)都表示了数列\({x,y,z,0,0,0,...}\)的答案。- 待完善
转移方程:
状态设计的优化
上述方案显然会TLE,于是考虑优化。
注意到dp数组是四维的,相对较大。考虑改为三维。
显然第四维非常重要不能删,所以应把前三维维护三个数改为用两维维护两个数。
设\(dp[x][y][k]\)表示对于数列\({x,y,a_{k},a_{k+1},...,a_{n-1},a_{n},0,0,0,...}\)的答案。
下面讨论问什么只维护两个数是可行的
- 由转移方程可以看出每次转移后考虑答案的区间会向右移动1,所以虽然操作对三个数有效,但区间向右平移后第三个数变成了第二个。
- 之所以最后一维的k可以表示\({a_{k},a_{k+1},...,a_{n-1},a_{n},0,0,0,...}\),是因为他们都是原数列中的数。第三个数在修改前也是原数列中的数所以可以用k表示
同样的原因也可以发现我们至少要维护一个数
- 只维护一个数的话根本无法得知当前位置可以进行的操作次数
- 只维护第\(i\)个数时,由于在\(i-1\)处的操作(即a[i-1]-1,a[i]-1,a[i+1]+1),第\(i+1\)个数可能不是原数组中的数,所以不能用k表示
新的状态转移方程和边界条件
暂缺
DP数组的大小分析
由边界条件2可知,第三维大小为 \(n+2\)。
显然第一、二维的大小为数列中数的最大值。
数列中数的初始最大值为50,数列非零位最长长度为50,欲求若干次操作后最大值的上界,不妨假设
- 初始数列为\({50,50,50,...,50,50,0,0,0,...}\) (50个50)
- 支持操作A:使\(a_{i-1}-1,a_{i}+\frac{1}{2}\)
- 支持操作B:使\(a_{i+2}-1,a_{i}+\frac{1}{2}\)
显然,由上述假设得到的答案大于等于若干次操作后最大值
\(a_{49},a_{48}\)对\(a_{50}\)的贡献为\(\frac{1}{2}(50+50)\)
\(a_{47},a_{46}\)对\(a_{50}\)的贡献为\(\frac{1}{4}(50+50)\)
\(a_{45},a_{44}\)对\(a_{50}\)的贡献为\(\frac{1}{8}(50+50)\)
...
于是第一、二维的大小为

浙公网安备 33010602011771号