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。
输入文件第一行包含两个正整数N和M。
第二行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.