http://acm.scs.bupt.cn/onlinejudge/showproblem.php?problem_id=1586
题意:
一共有K(K<=50)种字母,组成一个长度为L(L<=10^18)的串.
这个串需满足要求:
对任意的 1<=i<=L , 以及任意的 1<=k1,k2<=K 且 k1!=k2, 在前缀 s[1..i]中,字母k1的个数和字母k2的个数之差的绝对值<=2.
例如: abac是合法的; 而abbbc不合法, 因为前缀abbb中字母b和c的个数相差为3.
建立状态:
从<=2 入手找状态. 可以设前c个字母中, 最小个数为m, 字母数为m的种类为i, m+1的种类为j, m+2的种类为k. 化简状态可得 比最小个数多1的种类为i,比最小个数多2的种类为j. 而经过数学推导(不懂), 可知 j+2k<K, 也就是当 c%K 已知时, 可直接由k确定i和j. 这样状态数为 50*50=2500, 还是不能用矩阵法. 进一步思考, 由c%K=0时的结果可以推出c%K=1时的结果,递推可把c%K=0...K-1的结果都求出. 而要求L步的结果数,实际上并不用去管是1步1步走,还是2步2步走. 所以我们可以直接一次走K步! 这样就把c%K这一维状态也消除了.
于是可以设矩阵m[i,j]为c%K=0时,k经过K步从i转移到j的方法数.
这样先求出 L-L%K 步的方法数, 最后 L%K 步直接dp即可.
整体复杂度为 K^3*log(L/K).
本题关键: 由k和c%K唯一确定i和j; 一次走K步, 消除状态c%K, 实际上不同c%K对应的状态是冗余的, 因为不用去管中间的过程.
posted on 2009-06-29 22:18
wolf5x 阅读(420)
评论(0) 编辑 收藏 引用 所属分类:
acm_icpc