一切问题先抽象出数学模型来再去做
今后遇到比较大的数时,比较难算的运算时,可以考虑是否可以通过
1.循环节 例如做的400百年就是一个循环 星期与日期相同 如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
else
{
low=mid;
zmax=max(zmax,mid);
}
这种二分的判断方式适用于高精度问题(小数的二分)
8 高精度问题一般是较小的数+eps与较大的数进行相等的比较
9 1 超时的原因 时间复杂度, 2 数值超过了最大值了,变成负的的了。 如在二分的时候。。
10 数位dp 的值一律用 long long 或 unsigned long long ,特别容易爆,所以wa时一定要检查是不是爆了