小技巧。


一切问题先抽象出数学模型来再去做


今后遇到比较大的数时,比较难算的运算时,可以考虑是否可以通过

1.循环节         例如做的400百年就是一个循环 星期与日期相同
2.经过几轮之后就不改变的

         如HDU5239            线段树的题  一个数的平方取(2^63-2^31 ==9223372034707292160)  重复有限次就不会改变了


     等特性来减少时间

3。dp题做题先写出好想的递推式,然后再优化,根据时间复杂度或空间复杂度来优化

      如  HDU  5542      通过树状数组将n^3优化到n^2logn

      还有SDUT 2169   通过剪枝优化



   超时了的题先尝试剪枝再去改其他思路:

4.剪枝技巧:1.是遍历的结果比现有的结果还要大(小)即 更加不符合条件时就舍弃接下来的过程

            例如:1.DFS()中   if(mi>=Mi)      ///剪枝
                                         return ;
                                    if(sum==0)
                                {
                                  Mi=min(Mi,mi);
                                   return;
                                 }

                      2.或者DFS中已经找到结果了就用标记变量 进行剪枝,if(flag) return ;

                      3.  dp中用于减少for的次数

                     4.记忆化搜索

5.

dp[p][m][have][geowei]:p:处理的数位,m:该数对13取模以后的值,have:是否已经包含13 ,gaowei结尾的数

尝试用二维数组去写dp[][] 加上各种标记,结果超时了,用四维就不用纠结,各种情况的状态了。

记忆化搜索用多维一般会比 维数少的更好控制,更不易超时(当维数少的记忆化搜索超时时 改用更多维数去记忆
 ,来减少时间消耗。因为剪枝剪得不好造成的)
   例如数位dp时


6.遇到无思路问题:一:先分析样例: 1 先打表分析样例    2手写几组分析样例。


7。二分类问题,(也可包括三分)


       if(get(mid)==x){

       ans=mid; break;

        }

       else if(get(mid)>x)    high=mid-1;

      else low=mid+1;                                                                                  //是双向唯一的映射

上面的二分方法的判断条件 只适用于 mid 唯一映射一个值得情况,即 一个mid是唯一的对应一个get(mid);


if(get(mid)

else   {

ans=mid;            //也可以求最大值ans=max(mid,ans),最小值ans=min(mid,ans);

high=mid-1;

}                                                      ///适应于多对一的映射

这种方法适用于  多个不同的mid 对应相同的get()值, 并且会使ans 取满足条件的最小的mid值


if(num                 high=mid;  
            else  
            {  
                low=mid;  
                zmax=max(zmax,mid);  
            } 
 这种二分的判断方式适用于高精度问题(小数的二分)


8 高精度问题一般是较小的数+eps与较大的数进行相等的比较


9   1  超时的原因 时间复杂度, 2  数值超过了最大值了,变成负的的了。 如在二分的时候。。


10   数位dp 的值一律用 long long 或 unsigned long long ,特别容易爆,所以wa时一定要检查是不是爆了

你可能感兴趣的:(总结与计划)