NOIP复赛复习资料汇总.docx
《NOIP复赛复习资料汇总.docx》由会员分享,可在线阅读,更多相关《NOIP复赛复习资料汇总.docx(49页珍藏版)》请在冰豆网上搜索。
NOIP复赛复习资料汇总
NOIP复赛知识总结
(一)Pascal过程与函数调用
*abs(x):
y
取x的绝对值,x与y可为整型或实型。
*random(x):
y
在0-x之间的整数中随机找一个整数,x与y均为整型。
*sin(x):
y;cos(x):
y;arctan(x):
y;exp(x):
y;ln(x):
y
均与数学运算一致,三角函数返回的均为弧度,转换成角度即乘以Pi除以180.
*copy(str,n1,n2):
substr
从字符串str中取从第n1个字符开始长度为n2个字符的子串substr.n1和n2是整型表达式,如果n1大于s的长度,则返回空字符串。
如果指定的n2大于第n1个字符后剩下
的字符数,则返回剩下的字符串。
*pos(substr,str):
num
查找substr是否为str的子串,若是则返回substr在str中的起始位置,若否则返回0.
*val(str,int,code)
将字串str转为数值型数据存入int,如果字符串无效,其中非法字符的下标放在Code中;否则,code为零。
*str(num,str)
将num表达式转成字符串str。
*delete(str,n1,n2)
从原字符串str中删去一个从n1开始长度为n2的子串,如果Index比s长,不删除
任何字符。
如果指定的Count大于从第1ndex大到结尾的字符数,删除剩余部分。
*Insert(Source:
String;VarS:
String;Index:
Integer)
Source是字符串表达式。
S是任意长度的字符串变量。
Index是整型表达式。
过程Insert
把字符串Source插入字符串S中第1ndex个字符开始的位置上。
如果字符串比255个字符
长,则将第255后面的字符截去。
.
二、小技巧
1.ord('0')=48;ord('A'):
=65;ord('a')=97;chr(32)=’‘;chr(33)=’!
’;
2.求x^y:
int(exp(y*ln(x)))
3.求x的n次方根:
exp(1/n*ln(x))
4.标识符不能以数字开头,其中不能有空格,点等符号。
5.通常编译器只能识别标识符的前8个字符。
6.规定false=0,true=1;
7.除实型外其他均为左留空,右看齐,实型向小数点看齐。
(二)排序(快排、冒泡、堆排):
快速排序不稳定
[算法描述]
设有一无序数组a有n个元素.
1.以数组a的中点元素为参考值;
2.将中点左边大于(或小于)参考值的与中点右边小于(或大于)参考值的元素互换位置;
3.对中点左边的元素执行快排操作;
4.对中点右边的元素执行快排操作.
[源程序]
procedureqsort(vara:
arraytype;lx,rx:
longint);
vari,j,t,x:
longint;
begin
i:
=lx;j:
=rx;
x:
=a[random(j-i+1)+i];
repeat
while(a[i]a[i]>x
while(a[j]>x)dodec(j);//降序:
x>a[j]
if(i<=j)then
begin
t:
=a[i];a[i]:
=a[j];a[j]:
=t;//如果是为记录数组排序的话,t必须是记录类型的
inc(i);dec(j);
end;
until(i>j);
if(lxif(iend;
堆排序不稳定
procedureheap(varr:
arrtype;nn,ii:
integer);{该过程为调整为大根堆的过程,大根堆排序后是mintomax}
varx,i,j:
integer;
begin
i:
=ii;
x:
=r[ii];
j:
=2*ii;
whilej<=nndo
begin
if(j=j+1;{小根堆:
(jr[j+1])}
ifx=r[j];i:
=j;j:
=j*2;end{小根堆:
x>r[j]}
elsej:
=nn+1;
end;
r[i]:
=x;
end;
procedureheapsort(n:
integer);{堆排序}
fori:
=ndiv2downto1do{建立初始堆,且产生最大值a[1]}
heap(a,n,i);
fori:
=ndownto2do{将当前最值交换到最终位置上,再对前i-1个数调整}
begin
temp:
=a[1];a[1]:
=a[i];a[i]:
=temp;
heap(a,i-1,1);
end;
(三)常用数据类型
Byte0..2551
Shortint-128..1271
Smallint-32768..327672
Word0..655352
Integereithersmallint,longintorint64size2,4or8
Longint-2147483648..21474836474
Int64-9223372036854775808..92233720368547758078
QWord0..184467440737095516158
结论,FP中最佳类型当属longint可以有正负数,速度一流~若要节约,则可以试试word,不推荐Integer
(四)高精度
高精度数的定义:
type
hp=array[1..maxlen]ofinteger;
1.高精度加法
procedureplus(a,b:
hp;varc:
hp);
vari,len:
integer;
begin
fillchar(c,sizeof(c),0);
ifa[0]>b[0]thenlen:
=a[0]elselen:
=b[0];
fori:
=1tolendobegin
inc(c[i],a[i]+b[i]);
ifc[i]>10thenbegindec(c[i],10);inc(c[i+1]);end;{进位}
end;
ifc[len+1]>0theninc(len);
c[0]:
=len;
end;{plus}
2.高精度减法
proceduresubstract(a,b:
hp;varc:
hp);
vari,len:
integer;
begin
fillchar(c,sizeof(c),0);
ifa[0]>b[0]thenlen:
=a[0]elselen:
=b[0];
fori:
=1tolendobegin
inc(c[i],a[i]-b[i]);
ifc[i]<0thenbegininc(c[i],10);dec(c[i+1]);end;
while(len>1)and(c[len]=0)dodec(len);
c[0]:
=len;
end;
3.高精度乘以低精度
(1)
proceduremultiply(a:
hp;b:
longint;varc:
hp);
vari,len:
integer;
begin
fillchar(c,sizeof(c),0);
len:
=a[0];
fori:
=1tolendobegin
inc(c[i],a[i]*b);
inc(c[i+1],(a[i]*b)div10);
c[i]:
=c[i]mod10;
end;
inc(len);
while(c[len]>=10)dobegin{处理最高位的进位}
c[len+1]:
=c[len]div10;
c[len]:
=c[len]mod10;
inc(len);
end;
while(len>1)and(c[len]=0)dodec(len);{若不需进位则调整len}
c[0]:
=len;
end;{multiply}
(2)
programjk;
constmaxn=1000;
typehp=array[0..maxn]oflongint;
vari,j,n:
longint;a:
hp;b:
longint;
proceduremul(varh:
hp;k:
longint);
//h:
=h*k
vari:
longint;
begin
fori:
=0tomaxndoh[i]:
=h[i]*k;
fori:
=0tomaxn-1do
begin
h[i+1]:
=h[i+1]+h[i]div10;
h[i]:
=h[i]mod10
end;
end;
begin
a[1]:
=100;//两个乘数
b:
=888;
mul(a,b);//求a:
=a*b即888*100
i:
=maxn;
while(i>0)and(a[i]=0)doi:
=i-1;
forj:
=idownto1dowrite(a[j]);//输出计算后a的值
writeln;
end.
4.高精度乘以高精度
(1)
procedurehigh_multiply(a,b:
hp;varc:
hp);
vari,j,len:
integer;
begin
fillchar(c,sizeof(c),0);
fori:
=1toa[0]do
forj:
=1tob[0]dobegin
inc(c[i+j-1],a[i]*b[j]);
inc(c[i+j],c[i+j-1]div10);
c[i+j-1]:
=c[i+j-1]mod10;
end;
len:
=a[0]+b[0]+1;
while(len>1)and(c[len]=0)dodec(len);
c[0]:
=len;
end;
(2)
varn1,n2,n3:
string;
functionmul(n1,n2:
string):
string;
vara,b,c:
array[1..200]of0..9;
lena,lenb,lenc,i,j,x:
integer;
s:
string;ch:
string;
begin
lena:
=length(n1);lenb:
=length(n2);
fori:
=1tolenadoa[lena-i+1]:
=ord(n1[i])-ord('0');
fori:
=1tolenbdob[lenb-i+1]:
=ord(n2[i])-ord('0');
fori:
=1tolenado
begin
x:
=0;
forj:
=1tolenbdo
begin
x:
=a[i]*b[j]+xdiv10+c[i+j-1];
c[i+j-1]:
=xmod10;
end;
c[i+j]:
=xdiv10;
end;
lenc:
=i+j;
while(c[lenc]=0)and(lenc>1)dodec(lenc);
fori:
=lencdownto1do
begin
str(c[i],ch);
s:
=s+ch;
end;
mul:
=s;
end;
begin
assign(input,'input.dat');reset(input);
assign(output,'output.dat');rewrite(output);
readln(n1);readln(n2);
n3:
=mul(n1,n2);
write(n3);
close(input);close(output);
end.
5.高精度除以低精度
(1)proceduredevide(a:
hp;b:
longint;varc:
hp;vard:
longint);
{c:
=adivb;d:
=amodb}
vari,len:
integer;
begin
fillchar(c,sizeof(c),0);
len:
=a[0];d:
=0;
fori:
=lendownto1dobegin
d:
=d*10+a[i];
c[i]:
=ddivb;
d:
=dmodb;
end;
while(len>1)and(c[len]=0)thendec(len);
c[0]:
=len;
end;
(2)
programjk;
constmaxn=1000;
typehp=array[0..maxn]oflongint;
vari,j,n:
longint;c:
hp;b:
longint;
proceduredevide(varh:
hp;k:
longint);
//h:
=hdivk
vard,i,r:
longint;
begin
r:
=0;
fori:
=maxndownto0do
begin
d:
=10*r+h[i];
h[i]:
=ddivk;
r:
=dmodk
end;
end;
begin
c[1]:
=13;//被除数
b:
=5;//除数
devide(c,b);//求c:
=cdivb即13div5
i:
=maxn;
while(i>0)and(c[i]=0)doi:
=i-1;
forj:
=idownto1dowrite(c[j]);//输出计算后c的值
writeln;
end.
6.高精度除以高精度
procedurehigh_devide(a,b:
hp;varc,d:
hp);
var
i,len:
integer;
begin
fillchar(c,sizeof(c),0);
fillchar(d,sizeof(d),0);
len:
=a[0];d[0]:
=1;
fori:
=lendownto1dobegin
multiply(d,10,d);
d[1]:
=a[i];
while(compare(d,b)>=0)do{即d>=b}
begin
Subtract(d,b,d);
inc(c[i]);
end;
end;
while(len>1)and(c.s[len]=0)dodec(len);
c.len:
=len;
end;
7.精确计算n!
constmax=10000;n=2000;
vara:
array[1..max]of0..9;
i,j,k,x:
integer;
begin
k:
=1;a[k]:
=1;{a=1}
fori:
=2tondo{a←1*2*3….*n}
begin
x:
=0;{进位初始化}
forj:
=1tokdo{a=a*i}
begin
x:
=x+a[j]*i;a[j]:
=xmod10;x:
=xdiv10
end;
whilex>0do{处理最高位的进位}
begin
k:
=k+1;a[k]:
=xmod10;x:
=xdiv10
end
end;
fori:
=kdownto1dowrite(a[i]);{输出a}
end.
(五)常用算法
(1)字符串匹配的KMP算法
[源程序]
procedureget_next(s:
string;varnext:
inttype);
var
j,k:
integer;
begin
j:
=1;
k:
=0;
next[1]:
=0;
whilej<=length(t)do
if(k=0)or(t[j]=t[k])then
begin
j:
=j+1;
k:
=k+1;
next[j]:
=k;
end
elsek:
=next[k];
end;
functionindex(s,t):
integer;//求模式串t在主串s中的位置
var
next:
inttype;
i,j:
integer;
begin
get_next(t,next);
i:
=1;
j:
=1;
while(i<=length(s))and(j<=length(t))do
if(j=0)or(s[i]=t[j])then
begin
i:
=i+1;
j:
=j+1;
end
elsej:
=next[j];
ifj>length(t)thenindex:
=i-length(t)
elseindex:
=0;
end;
(六)普通树的遍历
(1)深度优先遍历
proceduretral(t,m){递归访问以t为根结点的含m棵子树的过程}
begin
ift<>nilthenbegin
write(t^.data,’’);{访问根结点}
forI:
=1tomdo{前序遍历各子树}
tral(t^.child[I],m);
end;
end;
(2)广度优先遍历
Constn=100;
Varhend,tail,I:
integer;
Q:
array[1..n]oftree;
t:
tree;{head,tail为队列的首尾指针,p为树的根结点}
Begin
Tail:
=1;head:
=1;t:
=p;{初始化}
Q[tail]:
=t;{t进队}
Tail:
=tail+1;
While(headBegin
T:
=q[head];{取出队首结点}
Head:
=head+1;
Write(t^.data,'');{访问某结点}
ForI:
=1tomdo{该结点的所有子结点按顺序进队}
Ift^.child[I]<>nilthen
begin
q[tail]:
=t^.child[I];
tail:
=tail+1;
end;
End;
End;
(七)二叉树
二叉树的性质
性质1:
在二叉树的第i层上至多有2^(i-1)个结点(i>=1)。
性质2:
深度为k的二叉树至多有2^k–1个结点(k>=1)。
性质3:
对任何一棵二叉树,如果其叶结点数为n0,度为2的结点数为n2,则一定满足:
n0=n2+1。
性质4:
具有n个结点的完全二叉树的深度为trunc(LOG2n)+1{2为底数,n为真数}
(2)二叉树的存储结构
1.顺序存储结构:
constm=树中结点数的上限;
typenode=record
data:
datatype;
prt,lch,rch:
0..m;
end;
treetype=array[1..m]ofnode;
vartree:
treetype;
(3)二叉树的遍历
(一)先序遍历
数组表示:
procedurepreorder(x:
integer);
begin
ifx<>0then
begin
write(tree[x].data);
preorder(tree[x].lch);
preorder(tree[x].rch);
end;
end;
(二)中序遍历
数组表示:
procedureinorder(x:
integer);
begin
ifx<>0then
begin
inorder(tree[x].lch);
write(tree[x].data);
inorder(tree[x].rch);
end;
end;
(三)后序遍历
数组表示:
procedurepostorder(x:
integer);
begin
ifx<>0then
begin
postorder(tree[x].lch);
postorder(tree[x].rch);
write(tree[x].data);
end;
end;
(4)普通树转化为二叉树:
输入格式:
顶点个数n(1<=n<=200)
以下n行其中第i行的元素以次为
结点i的数据值ai。
以后各元素为结点i的儿子序列,以0结束。
若ai后仅含一个0,则说明结点i为叶子结点。
输入样例:
18
r2340
a560
b70
c89100
w0
x11120
f0
s13140
t0
u0
d150
e0
i1617180
j0
h0
m0
o0
n0
程序样例:
fillchar(tree,sizeof(tree),0);
readln(n);
fork:
=1tondo
begin
read(tree[k].data);
read(j);
ifj<>0then
begin
tree[k].lch:
=j;tree[j].prt:
=k;
repeat
p:
=j;
read(j);
ifj<>0then
begin
tree[p].rch:
=j;tree[j].prt:
=p;
end;
untilj=0;
end;
readln;
end;
转换后可借用二叉树的前序遍历实现普通树的先根遍历
转换后可借用二叉树的中序遍历实现普通树的后根遍历
(5)用嵌套括号表示法输出二叉树
Procedureprint(bt:
tree);
Begin
Ifbt<>nilthenbegin
Write(bt^.data);
If(bt^.lchild<>nil)or(bt^.rchild<>nil)then
Begin
Write(‘(’);
Print(bt^.lchild);
Ifbt^.rchild<>nilthenwrite(‘,’);
Print(bt^.rchild);
Write(‘)’);
End;
End;
End;
(八)数论相关算法
1.求两数的最大公约数
functiongcd(a,b:
integer):
integer;
begin
ifb=0thengcd:
=a
elsegcd:
=gcd(b,amodb);
end;
2.求两数的最小公倍数
fun