NOIP2009提高组复赛题解

NOIP2009提高组复赛题解

2023年7月30日发(作者:)

1、潜伏者

program spy;

var

v: array['A'..'Z'] of boolean;

p, q: array['A'..'Z'] of char;

a, b: string;

j: char;

i: integer;

procedure stop;

begin

writeln('Failed');

close(input);

close(output);

halt;

end;

begin

assign(input, '');

reset(input);

assign(output, '');

rewrite(output);

readln(a);

readln(b);

fillchar(v, sizeof(v), 0);

for i := 1 to length(a) do

begin

v[a[i]] := true;

p[a[i]] := b[i];

q[b[i]] := a[i];

end;

for j := 'A' to 'Z' do

if not v[j] then stop;

for i := 1 to length(a) do

begin

if p[a[i]] <> b[i] then stop;

if q[b[i]] <> a[i] then stop;

end;

readln(a);

for i := 1 to length(a) do

write(p[a[i]]);

writeln;

close(input);

close(output);

end. 2、Hankson的趣味题

思路1:

根据最大公约数的定义,X必定为最大公约数的倍数,那么我们可以去枚举a1的倍数,然后去验证最大公约数和最小公倍数是否符合条件。期待分数:50。

程序1:

var

a0,a1,b0,b1,i,j,n,k,x,tot:longint;

function gcd(a,b:longint):longint;

begin

if b=0 then exit(a) else exit(gcd(b,a mod b));

end;

begin

readln(n);

for k:=1 to n do

begin

tot:=0;

readln(a0,a1,b0,b1);

for i:=1 to (b1 div a1) do

begin

x:=i*a1;

if b1 mod x=0 then

if gcd(a0,x)=a1 then

if (b0*x) div (gcd(b0,x))=b1 then begin inc(tot); end;

end;

writeln(tot);

end;

end.

思路2:

根据最小公倍数和最大公约数分解质因数指数的特殊关系进行优化。比如两个数,分解质因数可以得到以下的式子

A=p1^a1+p2^a2+p3^a3……

B=p1^b1+p2^b2+p3^a3……

例如6和21就可以分解成

6=2^1+3^1+5^0+7^0……

21=2^0+3^1+5^0+7^1……

则最大公约数=2^(min(a1,b1))+3^(min(a2,b2))+5^(min(a3,b3))+7^(min(a4,b4))…

最小公倍数=2^(max(a1,b1))+3^(max(a2,b2))+5^(max(a3,b3))+7^(max(a4,b4))…

那么我们可以先将b1分解质因数,在根据最大公约数和最小公倍数在指数上的关系,进行搜索。期待分数:100

程序2:

var

p,x,c:array[0..1000] of longint;

a0,a1,b0,b1,i,j,k,m,tot,t,n:longint;

function gcd(a,b:longint):longint;

begin

if b=0 then exit(a) else exit(gcd(b,a mod b));

end;

procedure dfs(i,sum:longint);

var

max,j:longint;

begin

if i>m then

begin

inc(tot);

p[tot]:=sum;

exit;

end;

max:=sum;

dfs(i+1,max);

for j:=1 to c[i] do

begin

max:=max*x[i];

dfs(i+1,max);

end;

end;

procedure work(b:longint);

var i,p:longint;

begin

i:=2;

p:=b;

while i<=sqrt(p) do

begin

if p mod i=0 then

begin

inc(m);

x[m]:=i;

c[m]:=0;

repeat inc(c[m]);

p:=p div i;

until p mod i<>0;

end;

inc(i);

end;

if p<>1 then

begin

inc(m);

x[m]:=p;

c[m]:=1;

end;

dfs(1,1);

end;

begin

readln(n);

for i:=1 to n do

begin

readln(a0,a1,b0,b1);

fillchar(p,sizeof(p),0);

fillchar(x,sizeof(x),0);

fillchar(c,sizeof(c),0);

m:=0;

tot:=0;

t:=0;

work(b1);

for j:=1 to tot do

if (gcd(p[j],a0)=a1) and ((p[j] div gcd(p[j],b0) * b0)=b1) then inc(t);

writeln(t);

end;

end.

思路三:

和思路二有异曲同工之妙。我们可以先预处理trunc(sqrt(2000000000))以内的质数,然后每读入一组数据,初始答案ans=1,然后我们循环质数,看a0、a1、b0、b1里面有多少个该质数因子,并且将这四个数分别消去所有该质数因子。我们设求出来的该因子个数分别是t1、t2、t3、t4。如果数据合法,那么t1>=t2,t3<=t4。根据最大公约数和最小公倍数的定义,我们要求的数所拥有的该质因子个数s必须要同时满足以下限制条件:

若t1>t2,则s=t2

若t1=t2,则s>=t2

若t3

这样,我们或者求出了s的范围,要么证明了不存在合法数字。如果s存在合法取值,我们就将ans乘上s的合法取值个数,否则直接输出0。

注意:如果循环结束后,a0>1或b1>1,那么此时a0或b1一定是超过我们枚举的数字范围的质数。这时我们特殊判断一下就行了。我们的时间复杂度是循环质数复杂度+分解因数复杂度。分解因数最坏是该数为2的若干次方,所以复杂度的上限是log(2000000000),很小。最慢的点在0.3秒以内出解。

程序3

program son;

var i,j,k,l,m,n,p,q,l2,r2,r,s,t,a0,a1,b0,b1,ans:longint;

prime:array[0..60000] of longint;

need:array[0..60000] of longint;

pd:boolean;

function pri(x:longint):boolean;

var g:longint;

begin

for g:=2 to trunc(sqrt(x)) do

if x mod g=0 then exit(false);

exit(true);

end;

begin

p:=1;prime[1]:=2;

for i:=3 to 50000 do if pri(i) then

begin

inc(p);

prime[p]:=i;

end;

read(n);

for t:=1 to n do

begin

read(a0,a1,b0,b1);

ans:=1;

fillchar(need,sizeof(need),255);

q:=p;

pd:=true;

for i:=1 to p do

begin

l:=0;r:=0;l2:=0;r2:=0;

while a0 mod prime[i]=0 do begin

inc(l);a0:=a0 div prime[i];

end;

while a1 mod prime[i]=0 do

begin

inc(r);a1:=a1 div prime[i];

end;

while b0 mod prime[i]=0 do

begin

inc(l2);b0:=b0 div prime[i];

end;

while b1 mod prime[i]=0 do

begin

inc(r2);b1:=b1 div prime[i];

end;

if l>r then need[i]:=r;

if l2

begin

if (need[i]>-1)and(need[i]<>r2) then

begin

pd:=false;break;

end;

need[i]:=r2;

end;

if need[i]=-1 then

if r2

begin

pd:=false;break;

end else ans:=ans*(r2-r+1);

end;

if i=p then

if a0>1 then

begin

inc(i);prime[i]:=a0;

l:=0;r:=0;l2:=0;r2:=0;

while a0 mod prime[i]=0 do

begin

inc(l);a0:=a0 div prime[i];

end;

while a1 mod prime[i]=0 do

begin

inc(r);a1:=a1 div prime[i];

end; while b0 mod prime[i]=0 do

begin

inc(l2);b0:=b0 div prime[i];

end;

while b1 mod prime[i]=0 do

begin

inc(r2);b1:=b1 div prime[i];

end;

if l>r then need[i]:=r;

if l2

begin

if (need[i]>-1)and(need[i]<>r2) then

begin

pd:=false;

end;

need[i]:=r2;

end;

if need[i]=-1 then

if r2

begin

pd:=false;

end else ans:=ans*(r2-r+1);

dec(i);

end;

if i=p then

if b1>1 then

begin

inc(i);prime[i]:=b1;

l:=0;r:=0;l2:=0;r2:=0;

while a0 mod prime[i]=0 do

begin

inc(l);a0:=a0 div prime[i];

end;

while a1 mod prime[i]=0 do

begin

inc(r);a1:=a1 div prime[i];

end;

while b0 mod prime[i]=0 do

begin

inc(l2);b0:=b0 div prime[i];

end;

while b1 mod prime[i]=0 do

begin

inc(r2);b1:=b1 div prime[i]; end;

if l>r then need[i]:=r;

if l2

begin

if (need[i]>-1)and(need[i]<>r2) then

begin

pd:=false;

end;

need[i]:=r2;

end;

if need[i]=-1 then

if r2

begin

pd:=false;

end else ans:=ans*(r2-r+1);

dec(i);

end;

if not pd then writeln(0) else writeln(ans);

end;

end.

程序4

program son;

var

p, x, c: array[1..10000] of longint;

n, m, t, i, j, k, a0, a1, b0, b1: longint;

function gcd(m, n: longint): longint;

var

r: longint;

begin

while n <> 0 do

begin

r := m mod n;

m := n;

n := r;

end;

gcd := m;

end;

procedure dfs(const i: longint; s: longint);

var

j: longint;

begin

if i > m then begin

inc(k);

p[k] := s;

exit;

end;

dfs(i + 1, s);

for j := 1 to c[i] do

begin

s := s * x[i];

dfs(i + 1, s);

end;

end;

procedure get(b: longint);

var

i: longint;

begin

m := 0;

i := 2;

while i <= sqrt(b) + 1e-6 do

begin

if b mod i = 0 then

begin

inc(m);

x[m] := i;

c[m] := 0;

repeat

inc(c[m]);

b := b div i;

until b mod i <> 0;

end;

inc(i);

end;

if b <> 1 then

begin

inc(m);

x[m] := b;

c[m] := 1;

end;

k := 0;

dfs(1, 1);

end;

begin

assign(input, '');

reset(input); assign(output, '');

rewrite(output);

read(n);

for i := 1 to n do

begin

read(a0, a1, b0, b1);

get(b1);

t := 0;

for j := 1 to k do

if (gcd(p[j], a0) = a1) and (p[j] div gcd(p[j], b0) * b0 = b1) then

inc(t);

writeln(t);

end;

close(input);

close(output);

end.

3、最优贸易

两次SPFA,用a[i]表示从起点开始到i结点能经过的最小值,用b[i]表示从终点延反向边到达i结点能经过的最大值。Ans=max(b[i]-a[i])。

const

maxn=100010;

maxm=1000010;

type

data=record

t,f,next:longint;

end;

var

n,m,ls:longint;

a,c,d,stack,v:axn]of longint;

f:axn]of boolean;

seg:axm]of data;

procedure insert_e(s,t,f1,f2:longint);

begin

inc(ls);

seg[ls].t:=t;

seg[ls].f:=f1;

seg[ls].next:=a[s];

a[s]:=ls;

inc(ls);

seg[ls].t:=s;

seg[ls].f:=f2;

seg[ls].next:=a[t];

a[t]:=ls; end;

procedure init;

var

i,j,k,l:longint;

begin

readln(n,m);

fillchar(a,sizeof(a),255);

ls:=0;

for i:=1 to n do read(v[i]);

for i:=1 to m do

begin

readln(j,k,l);

if l=1 then insert_e(j,k,1,2)

else insert_e(j,k,3,3);

end;

end;

function max(a,b:longint):longint;

begin

if a>b then exit(a) else exit(b);

end;

function min(a,b:longint):longint;

begin

if a

end;

procedure spfa1;

var

i,k,open,closed:longint;

begin

fillchar(c,sizeof(c),127);

fillchar(f,sizeof(f),0);

f[1]:=true;

open:=0;

closed:=1;

stack[1]:=1;

c[1]:=v[1];

while open

begin

inc(open);

k:=stack[open mod maxn];

f[k]:=false;

i:=a[k];

while i<>-1 do

begin

if (seg[i].f and 1=1)and(min(c[k],v[seg[i].t])

c[seg[i].t]:=min(c[k],v[seg[i].t]);

if not f[seg[i].t] then

begin

f[seg[i].t]:=true;

inc(closed);

stack[closed mod maxn]:=seg[i].t;

end;

end;

i:=seg[i].next;

end;

end;

end;

procedure spfa2;

var

i,k,open,closed:longint;

begin

fillchar(d,sizeof(d),0);

fillchar(f,sizeof(f),0);

f[n]:=true;

open:=0;

closed:=1;

stack[1]:=n;

d[n]:=v[n];

while open

begin

inc(open);

k:=stack[open mod maxn];

f[k]:=false;

i:=a[k];

while i<>-1 do

begin

if (seg[i].f and 2=2)and(max(d[k],v[seg[i].t])>d[seg[i].t]) then

begin

d[seg[i].t]:=max(d[k],v[seg[i].t]);

if not f[seg[i].t] then

begin

f[seg[i].t]:=true;

inc(closed);

stack[closed mod maxn]:=seg[i].t;

end;

end;

i:=seg[i].next;

end; end;

end;

procedure main;

var

i,ans:longint;

begin

spfa1;

spfa2;

ans:=0;

for i:=1 to n do

ans:=max(ans,d[i]-c[i]);

writeln(ans);

end;

begin

assign(input,'');

reset(input);

assign(output,'');

rewrite(output);

init;

main;

close(input);

close(output);

end.

程序2:

program trade;

const

maxn = 100005;

var

e1, e2: array[1..1000010] of record

t, next: longint;

end;

a, b, g1, g2, q: axn] of longint;

v: axn] of boolean;

n, i, f, r, k, p, s: longint;

procedure init;

var

m, s, i, j, k, z: longint;

procedure link(const i, j: longint);

begin

inc(s);

with e1[s] do

begin t := j;

next := g1[i];

end;

g1[i] := s;

with e2[s] do

begin

t := i;

next := g2[j];

end;

g2[j] := s;

end;

begin

read(n, m);

for i := 1 to n do read(b[i]);

fillchar(g1, sizeof(g1), 0);

fillchar(g2, sizeof(g2), 0);

s := 0;

for k := 1 to m do

begin

read(i, j, z);

link(i, j);

if z = 2 then link(j, i);

end;

end;

begin

assign(input, '');

reset(input);

assign(output, '');

rewrite(output);

init;

fillchar(v, sizeof(v), 0);

a[1] := b[1];

for i := 2 to n do a[i] := 100000;

f := 0;

r := 1;

q[1] := 1;

while f <> r do

begin

if f = maxn then f := 1 else inc(f);

k := q[f];

v[k] := false;

p := g1[k];

while p <> 0 do

begin with e1[p] do

if a[t] > a[k] then

begin

a[t] := a[k];

if a[t] > b[t] then a[t] := b[t];

if not v[t] then

begin

if r = maxn then r := 1 else inc(r);

q[r] := t;

v[t] := true;

end;

end;

p := e1[p].next;

end;

end;

s := 0;

fillchar(v, sizeof(v), 0);

f := 1;

r := 1;

q[1] := n;

v[n] := true;

if s < b[n] - a[n] then s := b[n] - a[n];

while f <= r do

begin

p := g2[q[f]];

while p <> 0 do

begin

with e2[p] do

if not v[t] then

begin

v[t] := true;

if s < b[t] - a[t] then s := b[t] - a[t];

inc(r);

q[r] := t;

end;

p := e2[p].next;

end;

inc(f);

end;

writeln(s);

close(input);

close(output);

end. 4、靶形数独

program d_1;

var usei,usej,usex:array[0..10,0..10] of boolean;

usep:array[0..100] of boolean;

maxi,a:array[0..10,0..10] of longint;

t,s,max,tot,i,j,k,n,m,p:longint;

x,y:array[0..100] of longint;

function solve(i,J:longint):longint;

var s,s1:longint;

begin

if (i<=j) then s:=i else s:=j;

if (10-i<=10-j) then s1:=10-i else s1:=10-j;

if (s=1) or (s1=1) then begin solve:=6; exit;end;

if (s=2) or (s1=2) then begin solve:=7; exit;end;

if (s=3) or (s1=3) then begin solve:=8; exit;end;

if (s=4) or (s1=4) then begin solve:=9; exit;end;

if (s=5) or (s1=5) then begin solve:=10;exit;end;

end;

function pr(i,j:longint):longint;

begin

pr:=(i-1) div 3*3+(j-1) div 3+1;

end;

procedure tryit(pp,now:longint);

var t,min,w,j:longint;

begin

if pp=s+1 then

begin

if now>max then

begin

max:=now;

maxi:=a;

end

end

else

begin

t:=0; min:=999999;

for i:=1 to s do

if (a[x[i],y[i]]=0) and (not(usep[i])) then

begin

w:=0;

for j:=1 to 9 do

if (usei[x[i],j]) and (usej[y[i],j]) and

(usex[pr(x[i],y[i]),j]) then

begin inc(w);

if w>=min then break;

end;

if w

begin

min:=w;

t:=i;

end;

end;

if min=0 then exit;

usep[t]:=true;

for j:=1 to 9 do

if (usei[x[t],j]) and (usej[y[t],j]) and

(usex[pr(x[t],y[t]),j]) then

begin

usei[x[t],j]:=false;

usej[y[t],j]:=false;

usex[pr(x[t],y[t]),j]:=false;

a[x[t],y[t]]:=j;

tryit(pp+1,now+solve(x[t],y[t])*j);

a[x[t],y[t]]:=0;

usei[x[t],j]:=true;

usej[y[t],j]:=true;

usex[pr(x[t],y[t]),j]:=true;

end;

usep[t]:=false;

end;

end;

begin

assign(input,'');

assign(output,'');

reset(input);

rewrite(output);

fillchar(usei,sizeof(usei),true);

fillchar(usej,sizeof(usej),true);

fillchar(usex,sizeof(usex),true);

tot:=0; max:=0; s:=0;

for i:=1 to 9 do

begin

for j:=1 to 9 do

begin

read(a[i,j]);

if a[i,j]<>0 then

begin usei[i,a[i,j]]:=false;

usej[j,a[i,j]]:=false;

usex[pr(i,j),a[i,j]]:=false;

t:=solve(i,j);

tot:=tot+t*a[i,j];

end;

if (a[i,j]=0) then

begin

inc(s);

x[s]:=i; y[s]:=j;

end;

end;

readln;

end;

fillchar(usep,sizeof(usep),false);

tryit(1,tot);

if max=0 then writeln('-1') else writeln(max);

close(input);

close(output);

end.

发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1690719154a407202.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信