NOIP2015模拟2

来源:互联网 发布:远景能源软件研发待遇 编辑:程序博客网 时间:2024/04/29 20:33

传送门

http://218.62.22.209:8080/problem.php?id=3172
http://218.62.22.209:8080/problem.php?id=3173
http://218.62.22.209:8080/problem.php?id=3174

T1 玛雅历

注意取模运算时的整除情况讨论

const t1:array[1..19]of string=('pop','no','zip','zotz','tzec','xul','yoxkin','mol','chen','yax','zac','ceh','mac','kankin','muan','pax','koyab','cumhu','uayet'); t2:array[1..20]of string=('imix','ik','akbal','kan','chicchan','cimi','manik','lamat','muluk','ok','chuen','eb','ben','ix','mem','cib','caban','eznab','canac','ahau');var a,b,aa,aaa:longint; n,ss:longint; i,j,k:longint; ans:array[0..18985,1..3]of longint; c,d:char; e,x:string; year,month,day,y1,y2:longint;begin readln(n); writeln(n); for i:=1 to n do  begin   readln(e); ss:=pos('.',e);   val(copy(e,1,ss-1),y1);   e:=copy(e,ss+2,length(e)-ss-1);   ss:=pos(' ',e);   x:=copy(e,1,ss-1);   val(copy(e,ss+1,length(e)-ss),y2);   aaa:=y2*365+y1+1;   for j:=1 to 19 do    if t1[j]=x    then begin aa:=j; break; end;   inc(aaa,(aa-1)*20);   if aaa mod 260=0   then begin    if aaa mod 260=0 then aaa:=(aaa div 260)-1 else aaa:=aaa div 260;    writeln(13,' ',t2[20],' ',aaa);   end   else begin    aa:=aaa mod 260; if aaa mod 260=0 then aaa:=(aaa div 260)-1 else aaa:=aaa div 260;    if aa mod 13=0 then day:=13 else day:=aa mod 13;    if aa mod 20=0 then month:=20 else month:=aa mod 20;    writeln(day,' ',t2[month],' ',aaa);   end;  end;end.

T2 密码

题目大意

给定一个密码B,在B的任意位置插入任意个数任意小写字符,得到加密后的字符串A,对A进行切割,切割方式为从前向后切任意个,从后也是,是切割后剩余部分仍保留包含B的完整信息

题解

为了不重复,我们枚举从开头删的个数0..length(B),举个例子
abcdabcabc
abc
(0,0..6) (1..4,0..3) (5..7,0)
也就是说我们先处理出A在B中的每个最紧凑的存在位置,对于相邻的两个,他们的起始位置和终止位置分别为L[i],R[i],L[i+1],R[i+1],我们可以发现,从头删到L[i]..L[i+1]-1,这(L[i+1]-L[i])种情况删除后面的方法是一致的,即(0..length(B)-R[i+1]+1),所以相邻的两个对于ans的贡献为(L[i+1]-L[i])*(0..length(B)-R[i+1]+1)

var x:array[0..300000,1..2]of longint; y:array[0..300000,1..26]of longint; i,j,k:longint; n,m:longint; a,b:ansistring; tt,len:longint; ans,c,d:int64;function f(i,j:longint):longint;begin if i<=0 then exit(-1); if j=1 then exit(i); f:=f(y[i,ord(b[j-1])-96],j-1);end;begin readln(a); readln(b); n:=length(a); m:=length(b); for i:=2 to n do  begin   for j:=1 to 26 do    if ord(a[i-1])-96=j    then y[i,j]:=i-1    else y[i,j]:=y[i-1,j];   if a[i]=b[m]   then tt:=f(i,m);   if tt<>-1 then begin inc(len); x[len,1]:=tt; x[len,2]:=i; end;  end; ans:=0; for i:=1 to len do  begin   c:=x[i,1]-x[i-1,1];   d:=n-x[i,2]+1;   inc(ans,c*d);  end; writeln(ans);end.

T3 独立集

题目大意

给定一串数字,用冒泡排序简图,找最大独立集,及一定在队立即内的数(好吧,你看不懂很正常……直接转去题目看好了…)

题解

经过分析后我们发现,其实是求这段数的LIS,及一定会在LIS内的数是那些,100000要写nlogn的LIS
正着扫一遍最长上升,倒着扫一遍最长下降,每个数的两个值加起来若为ans-1则在LIS内,
然后我们把不是的删掉,再做一遍LIS,如果LIS第i位不唯一,那么所有可以作为第i位的数都不一定在LIS中

const maxn=100000;var sum,y,z,w,f,g,x:array[0..maxn]of longint; i,j,k:longint; ans,anss,tt,n:longint;function find(a,b:longint):longint;var l,r,mid:longint;begin l:=1; r:=ans; while l<r do  begin   mid:=(l+r)>>1;   if b=1   then begin    if y[mid]>a    then r:=mid else l:=mid+1;   end   else begin    if z[mid]>a    then l:=mid+1 else r:=mid;   end;  end; exit(l);end;begin readln(n); for i:=1 to n do  read(x[i]); fillchar(y,sizeof(y),0); y[1]:=x[1]; ans:=1; f[x[1]]:=1; for i:=2 to n do  begin   if y[ans]<x[i]   then begin    inc(ans); y[ans]:=x[i]; f[x[i]]:=ans;   end   else begin    tt:=find(x[i],1); y[tt]:=x[i]; f[x[i]]:=tt;   end;  end; writeln(ans); anss:=ans; fillchar(z,sizeof(z),0); z[1]:=x[n]; ans:=1; g[x[n]]:=1; for i:=n-1 downto 1 do  begin   if z[ans]>x[i]   then begin    inc(ans); z[ans]:=x[i]; g[x[i]]:=ans;   end   else begin    tt:=find(x[i],2); z[tt]:=x[i]; g[x[i]]:=tt;   end;  end; x[0]:=0; for i:=1 to n do  if (g[x[i]]+f[x[i]]=anss+1)  then begin inc(x[0]); x[x[0]]:=x[i]; z[x[0]]:=i; end; fillchar(y,sizeof(y),0); y[1]:=x[1]; ans:=1; f[x[1]]:=1; for i:=2 to x[0] do  begin   if y[ans]<x[i]   then begin    inc(ans); y[ans]:=x[i]; f[x[i]]:=ans;   end   else begin    tt:=find(x[i],1); y[tt]:=x[i]; f[x[i]]:=tt;   end;  end;  for i:=1 to x[0] do  inc(sum[f[x[i]]]); if ans<>anss then writeln('!'); for i:=1 to x[0] do  if sum[f[x[i]]]=1  then begin inc(w[0]); w[w[0]]:=i; end; for i:=1 to w[0]-1 do  write(z[w[i]],' '); writeln(z[w[w[0]]]);end.
0 0
原创粉丝点击