noip算法总结2016

合集下载

NOIP常用算法

NOIP常用算法

NOIP常用算法
NOIP是一种全球性的竞赛,考试内容涉及编程算法、数据结构、数
学建模等,其中算法题目占大多数。

这些算法可以根据其特点分为两类:
低效算法和高效算法。

一、低效算法
1、暴力解法
暴力解法是最简单的算法,就是直接枚举所有情况,找出最优解。


的运行时间是指数级别的,不推荐使用。

2、贪心算法
贪心算法是一种在每一步选择中都采取在当前状态下最好或最优(即
最有利)的选择,从而希望导致结果是最好或最优的算法。

贪心算法的时
间复杂度一般来说为O(n)。

3、分治法
分治法是将一个规模较大的问题分解为若干个规模较小的子问题,分
别解决,然后将子问题的解结合起来构成原问题的解。

它主要依赖于把一
个复杂的问题分解成两个或更多的相同或相似的子问题,然后递归求解,
分治法的时间复杂度可以达到O(nlogn)。

4、动态规划
动态规划是一种利用最优子结构性质解决复杂最优化问题的算法,通
过分解问题,将原问题转换为若干子问题,然后按照一些顺序求解子问题,利用子问题的解得到原问题的解,它的时间复杂度通常是O(n2)。

二、高效算法
1、算法
算法是指在一定的空间内,按照一定顺序最优解。

noip基本算法

noip基本算法

NOIP(全国青少年信息学奥林匹克竞赛)基本算法包括枚举、排序、二分答案、二分查找、贪心法、搜索算法、树上算法、图上算法、数据结构等。

具体来说,这些算法涵盖了基础算法的各个领域,例如枚举可以用于找出所有可能的解决方案,排序则可以用于对数据进行整理,二分答案和二分查找则是快速寻找目标值的有效方法,贪心法则可以用于解决一些最优解的问题,搜索算法则可以用于在大量可能的选择中找到最优解,树上算法则可以用于解决与树形结构相关的问题,图上算法则可以用于解决与图形相关的问题,而数据结构则可以用于高效地存储和操作数据。

在具体使用时,需要根据具体问题的需求选择合适的算法。

NOIP知识点总结

NOIP知识点总结

1时间复杂度
时间复杂度的分析方法
2排序算法
(1)平方排序算法(冒泡,插入,选择)
shell排序算法
(2)nlogn排序算法
快速排序(qsort,sort)
归并排序(求逆序对个数)
*
外部排序(堆排序)
3 数论
模运算
集合论
素数(Eratosthenes筛法)
进位制
欧几里德算法(辗转相除法)
扩展欧几里德算法(同余)ax + by = gcd(a,b)解线性同余方程ax ≡b(mod n)
*
中国剩余定理
高斯消元(线性代数)
4 数据结构
广度/ 宽度优先搜索及剪枝
表达式计算
Hash表
并查集
Tarjan算法(LCA最近公共祖先)
树状数组
*
线段树
5 动态规划(DP)
背包问题(背包九讲)
LIS(最长上升子序列)的二分优化
DP的队列优化(LCIS,单调队列)
区间的DP
树上的DP(记忆化搜索)
6 图论
单源最短路(dijkstra,floyd,spfa)
最小生成树(prim,kruskal)
拓扑排序
floyd求最小环
求图的强连通分量
判断图中是否有环
差分约束系统(就是求最长路,用spfa)
others:
指针(链表,搜索判重,邻接表,散列表,二叉树的表示,多叉树的表示)位运算
高精度的加减乘除开方(开方直接二分)
乘法转加法神器:log。

NOIP复习资料(算法部分)

NOIP复习资料(算法部分)

1、高精度·读入与输出用字符串读入数据,用数组存储数据。

为了便于计算,可以用数组下标为0的元素记录该高精度数的长度。

{说明部分}const maxn=250;type arr=array[0..maxn] of integer; var a,b:arr;{读入部分}procedure init(var a:arr);var str:string;i,j,l:integer;beginreadln(str);fillchar(a,sizeof(a),0);a[0]:=length(str);for i:=1 to a[0] doa[i]:=ord(str[a[0]-i+1])-ord(‘0’);end;{输出部分}procedure print(a:arr);var i:integer;beginfor i:=a[0] downto 1 dowrite(a[i]);writeln;end;{主程序部分}begininit(a);init(b);print(a);print(b);end.·高精度加法(1)A[i]+B[i]+进位得到和M;(2)M mod 10是结果的第i位数字;(3)M div 10 是该位向下一位的进位。

procedure add(var a:arr;b:arr);var m,i,j:integer;begin if a[0]<b[0] then a[0]:=b[0];m:=0;for i:=1 to a[0] dobeginm:=m+a[i]+b[i];a[i]:=m mod 10;m:=m div 10;end;if m>0 then begininc(a[0]);a[a[0]]:=m;end;end;·高精度减法procedure minus(var a:arr;b:arr;var p:integer);{a-b}var i,j,k,m:integer;temp:arr;beginif a[0]>b[0] then p:=1else if a[0]<b[0] then p:=-1elsebegink:=a[0];while (a[k]=b[k]) and (k>0) do dec(k);if a[k]<b[k] then p:=-1;end;if p<0 thenbegintemp:=a;a:=b;b:=temp;end;for i:=1 to a[0] dobegina[i]:=a[i]-b[i];if a[i]<0 thenbegindec(a[i+1]);inc(a[i],10);end;end;k:=a[0];while (a[k]=0) and (k>1) do dec(k); a[0]:=k;end;·高精度减法(by yym大牛)if (length(n1)<length(n2)) or (length(n1)=length(n2)) and (n1<n2) thenbeginn:=n1;n1:=n2;n2:=n;write('-');end;lena:=length(n1);lenb:=length(n2);for i:=1 to lena do a[lena-i+1]:=ord(n1[i])-ord('0');for i:=1 to lenb do b[lenb-i+1]:=ord(n2[i])-ord('0');i:=1;while (i<=lena) or(i<=lenb) dobeginx:=a[i]-b[i]+10+x;c[i]:=x mod 10;x:=x div 10-1;i:=i+1;end;lenc:=i;while (c[lenc]=0) and (lenc>1) do dec(lenc);·高精度乘法(1)高精度乘以单精度procedure multi1( var a:arr;x:integer); var i,m:integer;beginm:=0;for i:=1 to a[0] dobegininc(m,a[i]*x);a[i]:=m mod 10;m:=m div 10; end;while m<>0 dobegininc(a[0]);a[a[0]]:=m mod 10;m:=m div 10;end;end;(2)高精度乘以高精度procedure multi2(var a:arr;b:arr); var c:arr;i,j,k,l:integer;beginfillchar(c,sizeof(c),0);for i:=1 to a[0] dofor j:=1 to b[0] doinc(c[i+j-1],a[i]*b[j]);for i:=1 to maxn-1 dobegininc(c[i+1],c[i] div 10);c[i]:=c[i] mod 10;end;k:=maxn;while (c[k]=0) and (k>1) dodec(k);c[0]:=k;a:=c;end;2、位运算运算符优先级Not 1(高)*,/,div,mod,and,shl,shr 2Xor,+,-,or 3In,=,<,>,>=,<=,<> 4(低)not 取反not(1)=0; not(0)=1;and 同真则真1 and 1=1; 0and 1=0; 0 and 0=0;or 有真则真1 and 1=1; 0 and 1=1; 0 and 0=0;xor 异真同假1 and 1=0; 0 and 1=1 0 and 0=0;shl a shl b就表示把a转为二进制后左移b位(在后面添b个0)。

NOIP算法总结与复习

NOIP算法总结与复习

NOIP算法总结与复习NOIP算法总结与复习(看了看李总的蓝⽪书,收获颇多,记下此⽂,以明志~~)(⼀)数论1、最⼤公约数,最⼩公倍数2、筛法球素数3、mod规律公式4、排列组合数,错排5、Catalan数6、康托展开7、负进制8、中位数的应⽤9、位运算(⼆)⾼精度算法1、朴素加法减法2、亿进制加法减法3、乘法4、除法5、亿进制读⼊处理6、综合运⽤(三)排序算法1、冒泡2、快排3、堆排4、归并(四)DP1、概念2、解题步骤3、背包类dp4、线性dp5、区间动态规划6、坐标型动态规划(规则类dp)7、资源分配型动态规划8、树型动态规划9、状态压缩的动态规划10、动态规划的⼀般优化⽅法(五)图论1、Floyd-Warshall2、Bellman-ford3、SPFA4、dijkstra5、prim6、kruskal7、欧拉回路8、哈密顿环9、flood fill(求图的强联通分量)10、最⼩环问题11、Topological sort12、次短路13、次⼩⽣成树(六)树1、堆2、⼆叉排序树3、最优⼆叉树(哈夫曼树)4、求树的后序遍历5、并查集及应⽤(七)分治1、⼆分查找2、⼆分逼近(注意精度问题)3、⼆分答案4、快排(见排序算法)5、归并排序(见排序算法)6、快速幂(⼋)贪⼼(九)搜索(⼗)其它1、离散化2、KMP3、字符串哈希4、常⽤字符串函数过程。

noip2016普及组解题报告

noip2016普及组解题报告

买铅笔【题目描述】P老师需要去商店买n支铅笔作为小朋友们参加NOIP的礼物。

她发现商店一共有 3种包装的铅笔,不同包装内的铅笔数量有可能不同,价格也有可能不同。

为了公平起见,P老师决定只买同一种包装的铅笔。

商店不允许将铅笔的包装拆开,因此P老师可能需要购买超过n支铅笔才够给小朋友们发礼物。

现在P老师想知道,在商店每种包装的数量都足够的情况下,要买够至少n 支铅笔最少需要花费多少钱。

【输入格式】输入的第一行包含一个正整数n,表示需要的铅笔数量。

接下来三行,每行用两个正整数描述一种包装的铅笔:其中第一个整数表示这种包装内铅笔的数量,第二个整数表示这种包装的价格。

保证所有的7个数都是不超过10000的正整数。

【输出格式】输出一行一个整数,表示P老师最少需要花费的钱。

【样例输入】572 250 3030 27【样例输出】54【算法分析】水题,整除、取余。

【AC代码】varn,i,a,b,p,ans:longint; beginreadln(n);ans:=maxlongint;for i:=1 to 3 dobeginread(a,b);if (n mod a)<>0 then p:=(n div a +1)*belsep:=(n div a)*b;if p<ans then ans:=p; end;writeln(ans);end.回文日期【题目描述】在日常生活中,通过年、月、日这三个要素可以表示出一个唯一确定的日期。

牛牛习惯用8位数字表示一个日期,其中,前4位代表年份,接下来2位代表月份,最后2位代表日期。

显然:一个日期只有一种表示方法,而两个不同的日期的表示方法不会相同。

牛牛认为,一个日期是回文的,当且仅当表示这个日期的8位数字是回文的。

现在,牛牛想知道:在他指定的两个日期之间包含这两个日期本身),有多少个真实存在的日期是回文的。

一个8位数字是回文的,当且仅当对于所有的i ( 1 <=i<= 8 )从左向右数的第i 个数字和第9-i个数字(即从右向左数的第i个数字)是相同的。

Noip算法总结

Noip算法总结
第二题超难(我觉得。。)
大致应该拿280左右
Noip_01_p
1数的计数
2最大公约数最小公倍数
3求先序排列
4装箱问题
总结
方法:dfs即可
难度:*
方法:分解质因数+乘法原理
难度:*
方法:递归+字符串处理
难度:*
方法:动态规划
难度:*
本套题目拿满分不难
Noip_02_p
1级数求和
2选数
3产生数
4过河卒
总结
难度:*
方法:用链表模拟增删和替换操作即可
难度:*
方法:构造+递归
根据邻接矩阵的对称性
(详见附图1)
难度:**
第四题不好想,其他没什么,应该考到300+吧。
Noip_97_p
1方格棋盘
2三角形枚举
3街道走向
总结
方法:枚举矩形(正方形)的大小然后直接算。
难度:*
备注:第4组数据有误
应改为:
输入:20 20
5灯的排列
第一问直接dfs出一种排列的所有方案。
第二问将第一问的方案数乘上颜色数的阶乘
难度:
**
Noip_96_p
1乘法运算
2横竖斜格子
3字符串编辑
4比赛安排
总结
方法:高精度/模拟
注意到范围在100以内。
直接用int读入,每一位拆出来乘一下,做个样子就可以了。
难度:*
方法:直接算
或许纯粹考察的while语句。
(本题数据规模模拟即可)
难度:*
方法:动态规划
难度:*
方法:递推+高精度
难度:***
前三题基本上是送分,第四题较难ቤተ መጻሕፍቲ ባይዱ理应拿310分或更高。

NOIP算法整理

NOIP算法整理

目录搜索 (4)DFS (4)框架 (4)优化 (4)BFS (4)框架 (4)优化 (5)排序 (5)冒泡排序 (5)选择排序 (5)插入排序 (6)桶排序 (6)快速排序 (7)堆排序 (7)数学定理 (8)中国剩余定理 (8)康托展开 (9)错排通项 (9)费马大定理 (9)费马小定理 (9)逆元 (9)欧拉函数 (10)Stirling数 (10)Stirling's approximation (10)数论 (11)GCD&LCM (11)素数 (11)快速幂 (12)模运算法则 (13)组合和全排列 (13)阶乘 (13)约瑟夫环问题 (13)Catalan数 (14)扩展欧几里德算法 (15)对自然数因子的计算 (15)矩阵乘法 (16)位运算 (16)动态规划 (18)步骤 (18)关键 (19)格式 (19)推荐参考资料 (19)推荐习题 (20)图论算法 (20)回路问题 (20)Euler回路 (20)Hamilton回路 (20)一笔画问题 (20)图的遍历 (23)DFS (23)BFS (23)最短路径 (25)dijkstra算法 (25)floyd算法 (26)spfa算法 (27)最小生成树 (29)prim算法 (29)Kruskal算法 (31)topology排序 (32)关键路径 (33)利用拓扑排序 (33)按照概念 (35)次短路 (36)次小生成树 (36)匈牙利算法 (37)博弈 (38)取对称状态 (38)取NIM值 (38)分治 (39)回溯 (41)N皇后 (41)Hanoi Tower (41)高精度计算 (42)高精度加法 (42)高精度减法 (42)高精度乘法 (44)高精度阶乘 (48)高级数据结构 (49)二叉树 (49)并查集 (51)树状数组 (52)线段树 (52)二叉搜索树 (54)进制转换 (59)1.将m进制数n转化成一个十进制数 (59)2.将十进制数n转换成m进制数 (59)搜索DFS框架procedure dfs(x);varbeginif达到目标状态then输出结果并退出过程;if满足剪枝条件then exit;for i:=1to搜索宽度dobegin备份现场;(注意如果现场使用了全局变量,则需要使用局部变量备份)dfs(参数+增量);恢复现场;end;优化(1)最优化剪枝:求最优值时,当前的状态无论如何不可能比最优值更优,则退出,可与展望结合剪枝(2)可行性剪枝:提前判断该状态是否能得到可行解,如不能则退出(3)记忆化搜索:对于已经搜索过的状态直接退出(4)改变搜索顺序:对于看起来希望更大的决策先进行搜索(5)优化搜索策略(6)预处理找到大体搜索翻译(7)改写成IDA*算法(8)卡时(注意现在联赛中禁止使用meml掐时)BFS框架初始化;把初始布局存入设首指针head=0;尾指针tail:=1;repeatinc(head),取出队列首记录为当前被扩展结点;for i:=1to规则数do{r是规则编号}beginif新空格位置合法thenbeginif新布局与队列中原有记录不重复tail增1,并把新布局存入队尾;if达到目标then输出并退出;end;end;until head>=tail;{队列空}优化判重的优化:hash,二叉排序树双向广搜或启发式搜索改写成A*算法二分优化排序冒泡排序var a:array[1..100] of longint;t,n,i,j:longint; procedure sort;beginfor i:=1to n-1do{与每个数都进行比较}for j:=1to n-i doif a[j]>a[j+1] thenbegint:=a[j];a[j]:=a[j+1];a[j+1]:=t;end;end;选择排序var a:array[1..100] of longint;t,n,i,j:longint;procedure sort;beginfor i:=1to n-1dofor j:=1+i to n do{大数沉小数浮}if a[j]>a[i] thenbegint:=a[j];a[j]:=a[i];a[i]:=t;end;end;插入排序var a:array[0..100] of longint;n,i,j,t:longint;procedure sort;beginfor i:=2to n dofor j:=1to (i-1) dobeginif (a[i]<a[j]) thenbegint:=a[j];a[j]:=a[i];a[i]:=t;end;end;end;桶排序var a,b:array[0..100] of longint;r,i,j,t,k,n:longint; procedure sort;beginfor i:=0to100do b[i]:=0;{为B数组清零,小桶内容清零} for i:=1to n do b[a[i]]:=b[a[i]]+1;{桶的序号就是那个要排序的东西;出现一次,桶里得旗数加一} for i:=0to100do{扫描所有的桶}beginif b[i]<>0then{桶里有旗}for j:=1to b[i] do write(i,'');{桶的序号就是那个数} end;end;快速排序var a:array[1..100] of longint;n,i,h,g:longint;procedure kp(l,r:longint);{变量不能与全局变量相同,否则会被抹去} var b,m,i,j,t:longint;begini:=l;j:=r;m:=a[(l+r) div2];{基准数最好从中间取}repeatwhile a[j]>m do dec(j);while a[i]<m do inc(i);{两侧的哨兵移动}if i<=j then{哨兵未碰面}{“=”利用repeat循环的性质,使repeat循环得以结束} begint:=a[j];a[j]:=a[ia[i]:=t;{交换两个哨兵的值}inc(j);dec(j);{哨兵继续运动}end;until i>j;if j>l then kp(l,j);if i<r then kp(i,r);{都是循环不结束后进行的动作}end;beginread(n);for i:=1to n do read(a[i]);kp(1,n); {“一”位置与“N”位置}for i:=1to n-1do write(a[i],'');write(a[n]);{防止多输出空格使程序结果出错}end.堆排序var a:array[1..100] of longint;n,i,b:longint;procedure jianshu(i:longint);beginwhile ((a[i]>a[i*2])or(a[i]>a[i*2+1]))and(i<=n div2) do{当父亲数大于子女数时并且他有孩子时进行}beginif a[i*2]<=a[i*2+1]{左儿子小于右儿子}thenbeginb:=a[i*2]; a[i*2]:=a[i];a[i]:=b;{左右儿子的值互换}jianshu(i*2);{继续为左儿子建树}endelsebeginb:=a[i*2+1];a[i*2+1]:=a[i];a[i]:=b;jianshu(i*2+1);{上同,不过是为右儿子建树}end;end;end;procedure tiao;beginwhile n<>0dobeginwrite(a[1]);a[1]:=a[n];n:=n-1;for i:=(n div2) downto1dojianshu(i);end;end;beginread(n);for i:=1to n doread(a[i]);for i:=(n div2) downto1dojianshu(i);tiao;end.数学定理中国剩余定理若有一些两两互质的整数m1, m2,… mn,则对任意的整数:a1,a2,...an,以下联立同余方程组对模数m1, m2,… mn 有公解:康托展开a[i]为当前未出现的元素中是排在第几个(从0开始)把一个整数X展开成如下形式:X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[2]*1!+a[1]*0!其中a[i]为当前未出现的元素中是排在第几个(从0开始),并且0<=a[i]<i(1<=i<=n)错排通项考虑一个有n个元素的排列,若一个排列中所有的元素都不在自己原来的位置上,那么这样的排列就称为原排列的一个错排。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

算法总结一、动态规划和递推dp一般的解题步骤:分析问题,弄清题意——从原问题中抽象出模型——根据模型设计状态,要求状态满足最优子结构和无后效性——直接设计状态有难度的话则需要考虑转化模型——根据设计的状态考虑转移——如果过不了题目要求的数据范围,则需要考虑优化由于动态规划涉及的内容太多,只言片语难以讲清,所以附件中放了很多篇关于动态规划的文章,大部分系原创,并附上了一些经典的论文,主要讲了DP的优化,一些特殊的状态设计技巧Dp和递推没有本质区别,都是用一些状态来描述问题,并记录下一些信息,根据已知信息推出未知信息,直到得到问题的解关于DP的优化有两篇神级论文,放在附件里面了,写的非常好。

二、图论及网络流最小生成树:克鲁斯卡尔算法和普利姆算法,——重要性质1:最小生成树上任意两点的路径的最大边最小——重要性质2:最小生成树的多解(方案个数)只与相同权值的的边有关(省队集训题生成树计数)最短路:spfa算法、堆+迪杰斯特拉算法Spfa算法是基于松弛技术的,随机图效果极佳,最坏(网格图或存在负权环)O(nm),适用于任意图,能够判断负权环——判负权环的方法:记录每个点当前从原点到它的最短路上边的条数,如果某次更新后这个条数>n-1则存在负权环堆+迪杰斯特拉则是用了贪心的思想,不断扩大确定dist的集合,同时更新dist,如果边权有负值就不能做,复杂度是O((n+m)logn)的拓扑排序:可以将有向图转化为一个线性的序列,满足一个点所有的前驱结点都出现在这个点在序列中的位置之前。

可以判断这个有向图是否有环——一个简单而实用的扩展:给树做类top排序,可以有类似的功能,即每次去掉叶子结点,将树转化为一个具有拓扑关系的序列——再扩展:树同构判断,可用类top确定树根是谁,再最小表示法+hash即可强连通分量、缩点:tarjan算法核心是每个点记一个时间戳ti[i], 另外low[i]表示i点能延伸出的搜索树中节点的ti[i]的最小值,还要维护个栈记当前路径上的点,low[i]初始化为ti[i],如果搜完i了,ti[i]=low[i]则当前栈顶到i的所有点会在一个强连同分量内。

var j,k:longint;begininc(time);ti[i]:=time;v[i]:=true;low[i]:=time;inc(ed);q[ed]:=i;j:=h[i];while j<>0 do begink:=point[j];if ti[k]=0 then begindfs(k);if low[k]<low[i] then low[i]:=low[k];endelseif v[k] then if ti[k]<low[i] then low[i]:=ti[k];j:=next[j];end;if ti[i]=low[i] then begininc(num);k:=0;repeatj:=q[ed];f[j]:=num;v[j]:=false;k:=k+a[j];if b[j] then bar[num]:=true;dec(ed);until q[ed+1]=i;vl[num]:=k;end;end;欧拉路:含义:不重复地经过每条边的一条路径,如果起点和终点相同则叫“欧拉回路”,起点和终点不同叫“欧拉路径”存在欧拉路径的条件:至多两个点的度为基数(回路则要求全都为偶数)实现:(非常简单)上面的代码中正边和反边的编号是相邻的,关注inc(ans[0])的位置,是在递归调用的后面哈密尔顿回路含义:经过所有点的一个回路这是个NPC问题,只有近似算法(暴搜就不提了)比较好用的是模拟退火,以环上相邻两点有边相连的个数作为估价值,随机化调整二分图匹配:最大匹配:匈牙利算法,理论O(nm),实际复杂度好很多最佳匹配:KM算法,理论O(n^2m),实际复杂度同匈牙利一样相当不错——重要性质:最小可行定标和= 最优匹配KM算法中构造了一个非常不错的不等式lx[i] + ly[j] >= w[i,j],有的题目可以利用这个不等式套KM求出最小可行定标和,如20101112 ti糟糕的传染网络流非常神奇的一个东西,数学味有余而图论味不足,通常用来解决限制条件太强,以至于无论如何都表示不了状态的题,很多经典例题见《网络流24题》通常使用的最大流算法是dinic,代码要背熟,一般能10分钟之内敲出来最大流最小割定理经典模型:最小割模型,最大权闭合图,平面图网络流转最小割——参考神文胡伯涛论文费用流相当于网络流的一个强化,能多处理一维信息。

具体来讲就是给边多加一个“费用”,每次增广的费用就是这条增广路的费用之和*流量。

费用流有最小费用最大流和最大费用最大流,用spfa每次找条最短(长)路增广即可最小费用最大流还可以用zkw算法加速,差不多比裸spfa+增广快10倍的样子(在二分图网络流上尤为明显),我和盾盾研究了一种更nb的费用流,我命名为“距离标号连续增广路费用流算法”,能够秒杀几千个点的稠密随机图,二分图就更不在话下了,速度几乎达到了dinic的三分之一的样子,而且实现非常简单!经典例题参考《网络流24题》三、贪心贪心的关键是找结论,同时给出证明,然后就可以利用这个结论来做题了当然,考场上对你猜出的结论给出证明通常是很难的,所以用贪心法解题需要丰富的经验,正确的“题感”,胆大心细才能搞出来由于经常要取最优值,所以常常与堆、平衡树等数据结构结合起来贪心+其他算法:由于贪心往往能大幅化简状态,利用问题的某些“单调性”,加上贪心的思想,往往能是问题大幅简化,从而结合其他算法解决问题经典例题:田忌赛马,利用贪心来确定状态四、分治分而治之的思想在信息学竞赛中是非常重要的,下面主要介绍一下分治的经典应用二分查找思想很简单,功能很强大,边界要注意,负数要特判(NOI2010 PIANO)在非负数范围内的二分一般写法如果是l := mid - 1或+ 1则mid := (l + r) div 2而如果是r := mid - 1 或+1则mid := (l + r + 1) div 2快速幂a^b = (a^(b div 2))^2 + ord(odd(b))*a取模也适用——扩展:求(1 + a + a^2 + a^3 + … + a^n) mod p的值O(logn)算法:分治1 + a + a^2 + a^3 + … + a^n= (1 + a + a^2 + a^3 + … + a^(n div 2))*a^(n div 2) + ord(odd(n))*a^n两个快速幂可以合到一起写快速排序,归并排序任何一本算法书上都会讲的,这里就略过了,值得一提的是快排记得加上随机化k := a[random(r - l + 1) + l]二分答案(0-1分数规划)当答案满足在解集空间中连续分布时可以使用二分答案,将最优性问题转化为判定性问题,通常标志:最大值最小等差分约束系统中有时也需要二分答案以解决最优性问题,顺便能多得到一个信息二分答案还有一个优势,那就是已经知道了答案,那就可能可以将一些直接做必须在线的操作转化为离线操作(也就是说,我可以排序然后判定),诸如要求你判定“第一句出现矛盾的话”之类的题目(poj 3657)0-1分数规划也是经典的利用二分答案来做的一类问题通常是要求你最小化f(x)/g(x)令ans = f(x)/g(x)则f(x) - g(x)*ans = 0重构权,将f(i) - g(i)*ans作为新权值,用相应算法求出一个“最小值”,判断是否>=0,接着二分即可详细说明及数学证明见集训队07胡伯涛论文树的分治一般用来解决树上的路径或统计类问题,每次只考虑跟树根有关的信息,然后递归分治处理树的分治通常有基于点或基于边的分治,基于点的难合,基于边的复杂度太高这里只介绍基于点的分治步骤:处理跟当前树根有关的信息重新计算子树大小在子树中选择重心为根,递归到相应子树处理因为每次选了重心,所以递归总共logn层,每层O(n)的复杂度,总复杂度就是O(nlogn) 更详细严谨的介绍见漆子超论文二分搜索直接搜的复杂度是指数级的的话,一般是40左右的数据量,hash一半,搜一半,搜后面的时候利用之前的hash信息合并出原问题的解而直接搜的复杂度达到阶乘级的话n一般就不超过20了,做法一般差不多经典例题:POI02szy,NOI2001方程的解数五、搜索作为信息学竞赛中的所谓“万能算法”,搜索可以说是计算机学科所具有的最大特点了,自然地,搜索算法的应用自然也是非常之广泛,除了专门的搜索题,搜索一般可以用来部分预处理,打表找规律,当然还有骗分搜索的一般步骤:确定状态——选择搜索方式(dfs、bfs)——确定产生式规则——开始搜索搜索的常见优化方式:改变状态表示这个需要根据题目而定,确定一个漂亮的状态表示,可能就有希望转向记忆化了,即使不行,搞出一个漂亮的状态表示是解决一道麻烦题的最重要的一步,再者,调试起来也会容易许多。

优化搜索顺序这个优化在多数搜索中能起到摧枯拉朽的提速效果,通常我们选择枝叶较少的儿子先扩展,例如大名鼎鼎的dancing Links,除了利用双向十字链表去除冗余状态,每次选择可扩展数最少的儿子扩展同样给它的神速创造了条件。

(poj的一道数独题,我在选择拿出去扩展的点的那个循环中<和<=的区别就是200ms和2000ms的区别)可行性剪枝以及最优性剪枝这是非常常用的剪枝思路之一,因题目而异,在迭代加深搜索中尤为重要一般思路:考虑每次解最多变优多少,从当前的层数来看还有多少改进空间,如果已经不可能成为解或更新答案则可以剪枝了——A*及IDA*算法:本质就是给搜索加上一个满足相容性的估价函数,然后用估价函数剪枝,理论上很牛B,实际上不常用,因为考场上很难想出满足那么多条件的估价函数,但记得一些常见模型的估价函数还是有价值的。

例如15数码的估价函数就可以选择除了0之外每个元素到自己该到的位置的曼哈顿距离之和,因为每次最多使一个数距离减少1,所以这个估价函数是相容的,再例如求k短路的A*算法就是用个堆维护min{ f(s) + g(s) }估价函数就是从汇点反搜的“反向最短路”的长度。

部分搜索+其他算法部分搜索+二分图匹配:楼天成《匹配算法在搜索问题中的巧用》经典例题:mt problem 2 milk(很郁闷的说,只用该算法仍不能ac之)六、数论和组合数学同余方程(组)#define (a mod b)->((a mod b + b) mod b)–>解决负数的问题解线性同余方程的方法:扩展欧几里德核心操作:求ax + by = gcd(a, b) = d先递归求a’y + b’(x mod y) = da’y + b’(x - x div y*y) = da’y + b’x – b’*(x div y)*y = db’x + (a’– b’*(x div y))*y = d有a = b’ b = a’ - b’*(x div y)边界:y = 0时,a = 1, b = 0解模方程ax mod b = c等价于解出ax + by = c无解的条件c mod gcd(a,b) <> 0求解ax +by = c令d = gcd(a, b), c’ = c div d求解原方程等价于求解ax + by = d, 求完后将答案乘上c’即可求ax mod b = c的最小正解的方法先求出一组ax + by = c的可行解x,y(实际上我们只要x)由a(x + k*b) mod b = c所以我们可以通过给x加上若干倍b使得a恰好大于0实际操作时,只要取x’ = x mod b就可以了,如果x’< 0 则x’ := x’ + b解同余方程组的方法:每次合并两个模方程,合到最后就能够解出来了核心操作:合并x mod a1 = b1x mod a2 = b2令x = a1*y + b1则(a1*y + b1) mod a2 = b2a1*y mod a2 = b2 - b1可以用扩展欧几里得求出y,从而求出最小正x同时满足两个方程合并之后变成x’ mod lcm(a1, a2) = x mod lcm(a1, a2)以此合并求解即可将带系数的方程化为不带系数的方法:ax mod b = c ⇔ax + by = c ⇔利用扩展欧几里得可解得x, y那么x的通解可以表示为x + k*(b div gcd(a, b))因此,原方程等价于x’ mod (b div gcd(a, b)) = x, x’是新的未知数,x是上面用扩展欧几里得解出来的东西,成功地等价地把系数消掉了素数和整除性问题判断素数的方法:O(sqrt(n)):从2枚举到sqrt(n)逐一判断即可均摊O(ln(n))的方法:筛选法利用费马小定理可以O(k*logn)地检验质数,但有一定概率出错(k是检验次数)组合计数类问题基本:排列和组合:C(N,M) = N!/(M!(N-M)!) P(N,M) = N!M!容斥原理:在计数时,必须注意无一重复,无一遗漏。

相关文档
最新文档