SRM540-div1-1-div2-2-ImportantSequence

来源:互联网 发布:unity3d开发的游戏案例 编辑:程序博客网 时间:2024/04/30 05:26
zz:http://www.strongczq.com/2012/04/srm540-div1-1-div2-2-importantsequence.html

题目原文:
http://community.topcoder.com/stat?c=problem_statement&pm=11842&rd=14732

题目大意:
     在黑板上写上N+1个正整数,每两个相邻正整数之间写上一个运算符'+'或者'-',运算符下面写上对这两个正整数执行该运算的结果。已知N个运算符用String operators表示,N个运算结果用int[] B表示,求原来的N+1个正整数序列有多少种可能。如果有无数种可能则返回-1.
     数据规模:N为[1,50],B元素取值范围[-10^9, 10^9]。

思路:
     将原来的正整数序列看作N+1个未知数,则每一个运算符及对应结果B[*]表示了一个等式约束,总共有N个等式。这个N个等式所表示的N个系数向量都是线性无关的,方程组的自由度为1,所以只要确定该正整数序列中某一项的取值那么其他所有项都确定了。我们可以试探为第一项赋值,然后观察所有其他项的取值,如果某项取值为非正数,那么显然该赋值是无效的。根据题目给出的数据规模,正整数的取值范围可以很大,不可能一一遍历第一项的所有取值情况。
     很容易观察到一个特点,如果第一个项取值加1,那么其他所有数的值变化也会是加1或者减1。具体的规律为,如果该项与第一项之间+符号的个数为奇数则是减1(称为下降项),否则是加1(称为上升项)。根据该规律可以通过以下方法得到正整数序列的不同取值个数:
  • 令第一项取值为1,逐个计算各项取值,记录下降项的最小值minDesc,上升项的最小值minAsc(注意第一项也是上升项)
  • 如果下降项minDesc取值非正,那么必然要增大对应项的取值,增大过程中minAsc会相应的减小,所以要保证minDesc上升到1的时候minAsc不能小于1,所以有minAsc - (1-minDesc) > 0, 即minAsc + minDesc > 1。相应的考虑minAsc取值为负时也会得到该公式。
  • 根据上面的结果minAsc + minDesc - 1就是边界间的所有不同取值数,所以不同序列的个数为minAsc + minDesc - 1。
     以上过程中需要注意一点,下降项的个数很可能是0,因为可能操作符都是'-',这个时候minDesc是没有有效值的,相应的不同序列个数有无数多种,应该返回-1.

Java代码:
public class ImportantSequence {    public int getCount( int[] B, String operators) {        long v = 1;        long minAsc = 1;        long minDesc = Long. MAX_VALUE;        boolean asc = true;        for (int i = 0; i < B. length; ++i) {            if (operators.charAt(i) == '-' ) {                v = v - B[i];            } else {                asc = !asc;                v = B[i] - v;            }            if (asc) {                minAsc = Math. min(minAsc, v);            } else {                minDesc = Math. min(minDesc, v);            }        }        if (minDesc == Long. MAX_VALUE) {            return -1;        } else {            return (int )Math.max(0, minAsc + minDesc - 1);        }    }}


原创粉丝点击