中山纪念中学 NOIP2010模拟赛

NOIP提高组模拟赛

 

 

 

 

题目名称

方程

1

Binary

中国结

目录

equation

cross

binary

wq

可执行文件名

equation

cross

binary

wq

输入文件名

equation.in

cross.in

binary.in

wq.in

输出文件名

equation.out

cross.out

binary.out

wq.out

每个测试点时限

1秒

1 秒

1秒

2秒

测试点数目

10

10

10

10

每个测试点分值

10

10

10

10

是否有部分分

题目类型

传统

传统

传统

传统

 

提交源程序须加后缀

对于Pascal语言

equaton.pas

cross.pas

binary.pas

wq.pas

对于C    语言

equaton.c

cross.c

binary.c

wq.c

对于C++  语言

equaton.cpp

cross.cpp

binary.cpp

wq.cpp

 

 

注意:最终测试时,所有编译命令均不打开任何优化开关

 


方程

【问题描述】

       给出非负整数N,统计不定方程X+Y^2+Z^3=N的非负整数解(x,y,z)的数量。

 

【输入文件】

 

       输入文件equation.in包含一个非负整数N

【输出文件】

       输出文件为equation.out。包含一个非负整数表示解的数量。

 

【输入样例】

5

【输出样例】

6

【样例解释】

6组解分别为(x,y,z)=(0,2,1),(1,2,0),(3,1,1),(4,0,1),(4,1,0),(5,0,0).

【数据规模和约定】

40%的数据中N≤10000;

60%的数据中N≤108

100%的数据中N≤1016


交错匹配

【问题描述】

有两排非负整数,A[1..N],B[1..M],如果A[i]=B[j]=K,那么可以在A[i],B[j]之间连一条线,称为一条K匹配,每个数至多连一条线。另外,每个K匹配都必须跟一个L匹配相交且K≠L!现在要求一个最大的匹配数。

例如:以下两行数的最大匹配数为8

1  2   3   3  2   4   1  5   1   3  5   10

 


3  1   2   3  2   4   12  1   5   5   3

【输入文件】

输入文件名为cross.in。

输入文件第一行包含两个正整数NM

第二行N个自然数表示A[i],

第三行M个自然数表示B[i]。

【输出文件】

输出文件名为cross.out。输出文件只有一个数字,即最大匹配数。

【输入样例I】

1211
   1 2 3 3 2 4 1 5 1 3 5 10

31 2 3 2 4 12 1 5 5 3

【输出样例I】

8

【输入样例II】

4 4
   1 1 3 3

11 3 3

【输出样例II】

0

【数据规模】

30%的数据满足N,M ≤ 30;

60%的数据满足N,M ≤ 200;

100%的数据满足N,M ≤ 1000, 0<所有数<=32767。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Binary

【问题描述】

求所有可以只用1和00拼成的长度为N的二进制数的个数除以15746的余数。比如当N=4的时候,有5个可能的二进制:0011,0000,1001,1100,1111。

 

【输入文件】

 

       输入文件binary.in包含一个正整数N

【输出文件】

       输出文件为binary.out。包含一个非负整数表示所求个数模15746的值。

 

【输入样例】

4

【输出样例】

5

【数据规模和约定】

40%的数据中N≤15;

100%的数据中N≤1000000。


中国结

【问题描述】

一个特殊的日子里,小Z决定编织一个中国结。在经过深思熟虑之后,他决定编织一个树型的中国结。这个中国结有N个节点,另有N-1条线连接这N个节点。节点1是树的根,每个节点有打结或未打结两种状态(初始时为未打结)。现有两种操作:

1. C       u     :将以u为根的子树上的所有节点状态取反。

2. Q              u     : 询问以u为根的子树上的所有节点中已经打结的有多少个。

【输入文件】

输入文件名为wq.in。

输入文件第一行包含一个正整数N

接下来N-1行表示N-1条线所连接的两个点。

紧接着一行一个正整数M表示有M个操作。

接下来M行每行一个操作。

【输出文件】

输出文件名为wq.out。对每个Q操作输出相应的值。

【输入样例】

5

12

13

24

25

5

Q1

C1

Q1

C2

Q1

 

【输出样例】

 

0

5

2

【数据规模】

40%的数据满足N ≤ 10000 , M≤ 20000;

100%的数据满足N ≤ 100000 , M≤ 100000。

 

【提示】

 

对于Windows下的测试,Pascal选手请在程序最前面加一行{$M 100000000},即开大系统栈。

 

 前面三题我很快就AC了。但是最后一题由于本人sb,调了好久。


第一题,只要循环一遍Z值,然后就能确定Y值有多少种,因为x=N-Y^2-Z^3,所以只要O(Z)即可,求y有多少种可以用sqrt直接求出

var
  n,y,z,ans:int64;
begin
  assign(input,'equation.in');
  assign(output,'equation.out');
  reset(input);
  rewrite(output);
  read(n);
  z:=0;
  ans:=0;
  while (z*z*z)<=n do
    begin
	  y:=trunc(sqrt(n-z*z*z));
	  ans:=ans+(y+1);
	  z:=z+1;
	end;
  writeln(ans);
  close(input);
  close(output);
end.



第二题,一道很经典的题目,用F[I,J]表示上面到i 下面到j最大已经连了多少

F[I,J]:=MAX{F[I-1,J],F[I,J-1],F[X-1,Y-1](A[I]=B[Y],B[J]=A[X],A[I]<>B[J]}
这样复杂度约等于O(N^3)

是会超时的,我们发现A[X]和B[Y]是可以通过预处理算出的。于是可以简化成O(N^2)

var
  n,m,i,j,k,max:longint;
  a,b:array[-10..1010] of longint;
  f,x,y:array[-10..1010,-10..1010] of longint;
begin
  assign(input,'cross.in');
  assign(output,'cross.out');
  reset(input);
  rewrite(output);
  fillchar(f,sizeof(f),0);
  read(n,m);
  for i:=1 to n do
    read(a[i]);
  for i:=1 to m do
    read(b[i]);
  
  for i:=1 to n do
    begin
	  k:=0;
	  for j:=1 to m do
	    if a[i]=b[j] then k:=j else x[i,j]:=k;
	end;

  for i:=1 to m do
    begin
	  k:=0;
	  for j:=1 to n do
	    if b[i]=a[j] then k:=j else y[j,i]:=k;
	end;
  max:=0;
  for i:=1 to n do
    for j:=1 to m do
	  begin
	    f[i,j]:=f[i-1,j];
		if f[i,j-1]>f[i,j] then f[i,j]:=f[i,j-1];
	    if (a[i]<>b[j]) and (x[i,j]>0) and (y[i,j]>0) then
		  begin
		    k:=f[y[i,j]-1,x[i,j]-1]+2;
			if k>f[i,j] then f[i,j]:=k;
		  end;
		if f[i,j]>max then max:=f[i,j];
	  end;
  writeln(max);
  close(input);
  close(output);
end.



第三题,很明显的斐波拉契数列。


var
  n,i:longint;
  f:array[0..1000010] of longint;
begin
  assign(input,'binary.in');
  assign(output,'binary.out');
  reset(input);
  rewrite(output);
  read(n);
  f[0]:=1;
  f[1]:=1;
  for i:=2 to n do
    f[i]:=(f[i-1]+f[i-2]) mod 15746;
  writeln(f[n]);
  close(input);
  close(output);
end.


第四题,先一遍DFS序列,然后就是区间的问题了。

记标记,更新,打印。

标记可以下传,也可以不下传。

本人sb 在exit后又加了个语句,结果无限wa。


{$M 100000000}
var
  zuo,you,u,v,p:array[-10..900000] of longint;
  vi,f:array[-10..900000] of boolean;
  i,tot,t,m,n,x,y,k:longint;
  next,a,b:array[-10..900000] of longint;
  c:char;
procedure build(k,l,r:longint);
  var
    m:longint;
  begin
    zuo[k]:=l;
	you[k]:=r;
    if (l=r) then exit;
	m:=(l+r) div 2;
	build(k*2,l,m);
	build(k*2+1,m+1,r);
  end;

procedure work(k:longint);
  var
    p,y:longint;
  begin
    vi[k]:=false;
    t:=t+1;
	u[k]:=t;
	p:=a[k];
	while p<>0 do
	  begin
	    y:=b[p];
		if vi[y] then work(y);
		P:=next[p];
	  end;
	v[k]:=t;
  end;

procedure insert(k,u,v:longint);
  var
    l,r,m:longint;
  begin
    l:=zuo[k];r:=you[k];m:=(l+r) div 2;
	if (l>=u) and (r<=v) then
	  begin
	    f[k]:=not f[k];
		exit;
	  end;
	if (u<=m) then insert(k*2,u,v);
	if (v>m) then insert(k*2+1,u,v);
	p[k]:=0;
	if f[k*2] then p[k]:=m-l+1-p[k*2] else p[k]:=p[k*2];
	if f[k*2+1] then p[k]:=p[k]+r-m-p[k*2+1] else p[k]:=p[k]+p[k*2+1];
  end;

function print(k,u,v:longint;var y:longint):longint;
  var
    l,r,m,x,z:longint;
  begin
    l:=zuo[k];r:=you[k];m:=(l+r) div 2;
	if (l>=u) and (r<=v) then
	  begin
	    x:=p[k];
		if f[k] then x:=(r-l+1-x);
                		y:=(r-l+1);
		exit(x);

		if x<y then writeln('asdsad');
	  end;
	x:=0;
	y:=0;
	z:=0;
	if (u<=m) then x:=print(k*2,u,v,z);
	y:=y+z;
	z:=0;
	if (v>m) then x:=x+print(k*2+1,u,v,z);
	y:=y+z;
	if (y<0) or (y<x) then
	  begin
	    writeln('fuck ',x,' ',y);
		writeln(p[1854],f[1854]);
		halt;
	  end;
	if f[k] then x:=y-x;
    exit(x);
  end;
begin
  assign(input,'wq.in');
  assign(output,'wq.out');
  reset(input);
  rewrite(output);
  read(n);
  t:=0;tot:=0;
  fillchar(a,sizeof(a),0);
  for i:=1 to n-1 do
    begin
	  read(x,y);
	  tot:=tot+1;
	  next[tot]:=a[x];
	  a[x]:=tot;
	  b[tot]:=y;

	  tot:=tot+1;
	  next[tot]:=a[y];
	  a[y]:=tot;
	  b[tot]:=x;
	end;
  fillchar(vi,sizeof(vi),true);
  fillchar(f,sizeof(f),false);
  fillchar(p,sizeof(p),0);
  build(1,1,n);
  work(1);
  readln(m);
  for i:=1 to m do
    begin
	  read(c);
	  readln(k);
	  y:=0;
	  if c='C' then  insert(1,u[k],v[k]) else writeln(print(1,u[k],v[k],y));
    end;
  CLOSE(INPUT);
  close(output);
end.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值