雀巢杯1&2

来源:互联网 发布:淘宝店铺免费模板 编辑:程序博客网 时间:2024/05/17 04:44

现在不是很想写,所以写得比较粗略,大家可以去http://blog.csdn.net/cjoilmd/article/details/6844342

想问题时总是容易钻牛角尖,一条路想不通不会换一条路。

day1:
problem1:最大子段积,有正有负。
记f[i]为正数最大,g[i]为负数最小,裸转移。
唯一麻烦的地方是要加科学计数法高精,但是可以转换成log运算。
长度可用换底公式len:=trunc(ans/ln(10));
ans:=exp(ans-len*ln(10))
problem2:枚举检验
用微元法可以看出,在中线之间是有一定单调性(远离人数和靠近人数不一样或相等),所以在中线处取极值,枚举每个人在两个门中线处。
此题有很多特殊数据。。。
problem3:倍增法

新学的算法,其实很简单,2^k可由2^(k-1)推出,走的时候用倍增思想加速即可(因为任何一个数可由多个2次方之和推出,类似于快速幂)。

ps:这道题找环裸做也可很快过

var ansi,len,n:longint;    ans:extended;    a,b,f,g:array[0..300000]of extended;procedure updata1(x:longint);begin  if f[x-1]+b[x]>b[x] then f[x]:=f[x-1]+b[x] else f[x]:=b[x];  if g[x-1]>-maxlongint then  g[x]:=g[x-1]+b[x]     else g[x]:=-maxlongintend;procedure updata2(x:longint);begin  if g[x-1]>-maxlongint then f[x]:=g[x-1]+b[x]     else f[x]:=0;  if f[x-1]+b[x]>b[x] then g[x]:=f[x-1]+b[x] else g[x]:=b[x]end;procedure updata3(x:longint);begin  f[x]:=0;  g[x]:=-maxlongint;end;procedure init;var i:longint;begin  readln(n);  for i:=1 to n do begin   read(a[i]);   if a[i]<0 then b[i]:=ln(-a[i]);   if a[i]>0 then b[i]:=ln(a[i])  end;  fillchar(f,sizeof(f),0);fillchar(g,sizeof(g),0);  g[0]:=-maxlongint;  for i:=1 to n do begin    if a[i]>0 then updata1(i)    else if a[i]<0 then updata2(i)    else updata3(i)  end;  ans:=-maxlongint;ansi:=0;  for i:=1 to n do   if ((f[i]>ans)and(f[i]<>0))or((f[i]=0)and(a[i]=0)and(ans<f[i])) then begin     ans:=f[i];ansi:=i   end;  if ans=-maxlongint then   for i:=1 to n do    if g[i]>ans then ans:=g[i];  if ans<>0 then begin    len:=trunc(ans/ln(10));    ans:=exp(ans-len*ln(10));    if ansi=0 then ans:=-ans;    if len=0 then begin writeln(ans:0:3);exit end;    write(ans:0:3);writeln('E',len)   end  else writeln('0.000')end;begin  assign(input,'key.in'); reset(input);  assign(output,'key.out'); rewrite(output);   init;  close(input); close(output);end.

uses math;var n,l,ans,s,max,m,anss:int64;    d,p:array[0..300]of int64;procedure doit;var i,j:longint;begin  i:=1;j:=1;  while p[j]<=d[i]+s do begin   max:=max+d[i]+s-p[j];inc(j)  end;  for j:=j to m do   if i<>n then begin    while (i<>n)and(s+d[i+1]<=p[j]) do inc(i);    if i=n then break;    max:=max+min(abs(p[j]-d[i]-s),abs(d[i+1]+s-p[j]))   end   else break;  if i=n then  for j:=j to m do max:=max+abs(d[n]+s-p[j])end;procedure init;var i,j:longint;    ll:int64;begin  readln(l);l:=l*10;  readln(m);  for i:=1 to m do begin read(p[i]);p[i]:=p[i]*10 end;readln;  readln(n);  d[1]:=0;  for i:=2 to n do begin read(d[i]);d[i]:=d[i]*10 end;readln;  ans:=0;anss:=0;  s:=0;max:=0;doit;  if max>ans then begin anss:=s;ans:=max end;  s:=l-d[n];max:=0;doit;  if max>ans then begin anss:=s;ans:=max end;  for i:=1 to n-1 do   for j:=1 to m do if d[i]<p[j] then begin     ll:=(d[i+1]-d[i])>>1;     s:=(p[j]-ll)-d[i];     max:=0;     if (s>=0)and(s<=l-d[n]) then doit;     if (max>ans)or((ans=max)and(s<anss)) then begin anss:=s;ans:=max end;   end;  writeln(anss/10:0:1,' ',ans/10:0:1)end;begin  assign(input,'boat.in'); reset(input);  assign(output,'boat.out'); rewrite(output);    init;  close(input); close(output);end.

const max=30;var n,k,ans,mo:longint;    m:ansistring;    f,g:array[1..10000,'A'..'Z',0..max]of longint;    d:array[0..max]of longint;procedure inf;begin assign(input,'source.in');reset(input); assign(output,'source.out');rewrite(output)end;procedure ouf;begin close(input);close(output)end;procedure doit1(var i:longint);var r,p:longint;    ch:char;begin  r:=0;inc(i);  while m[i]<'A' do begin    r:=r*10+ord(m[i])-48;inc(i)  end;  ch:=m[i];inc(i);//  ans:=(ans+g[k,ch,0]) mod mo;k:=f[k,ch,0];  p:=0;//dec(r);  while r<>0 do begin    if r and 1=1 then begin ans:=(ans+g[k,ch,p]) mod mo;k:=f[k,ch,p] end;    inc(p);    r:=r>>1  endend;procedure doit2(i:longint);var ch:char;begin  ch:=m[i];  ans:=(ans+g[k,ch,0])mod mo;k:=f[k,ch,0]end;procedure init;var i,j,l,x,y:longint;    ch:char;begin  readln(n,k);  fillchar(f,sizeof(f),0);fillchar(g,sizeof(g),0);  for i:=1 to n do begin   for j:=1 to k do begin     read(x,y);     f[i,chr(j+64),0]:=x;     g[i,chr(j+64),0]:=y;   end;   readln  end;  readln(m);l:=length(m);  readln(mo);  for ch:='A' to chr(k+64) do  for j:=1 to max do   for i:=1 to n do begin    f[i,ch,j]:=f[f[i,ch,j-1],ch,j-1];    g[i,ch,j]:=(g[i,ch,j-1]+g[f[i,ch,j-1],ch,j-1]) mod mo;   end;  d[0]:=1;  for i:=1 to max do d[i]:=d[i-1]<<1;  i:=1;k:=1;ans:=0;  repeat    if m[i]='[' then doit1(i)    else doit2(i);    inc(i)  until i>l;  writeln(ans)end;begin inf; init; oufend.

day2:

problem1:二分查找

二分答案,判断前多少个数的奇偶检验。

xor裸做常数好也可过

其实有个奇葩优化,只统计前100万个,因为数据水所以可以过。

problem2:最短路径树个数

根据分层图


到各个点只能选连到它边的其中之一,所以有边数中取法,乘法原理累乘即可

problem3:奇葩dp or 打表

打表就不说了。

dp我还没实现,f[i,j,k,p],表示个位置和为i,当前考虑到第j位,前j-1各位置之和为k,mod mo 为 p 的满足要求的数的个数,这是奥特曼的dp,因为我还没怎么理解,所以只提一下,下面贴题解:

因为一个数各位数字的和是logn级别的,因此可以考虑枚举这个和,假设是用变量mo记。

然后可以预处理f[mo][i][c][j]表示当前还有后i位没有确定(每一位可以任取0~9),后面所有数字的和为c,前面已经确定的若干位mod mo = j的方案数。

转移是枚举i这位,

F[mo][i][c][j]= ∑f[mo][i-1][c-k][(j*10+k)mod mo] (k = 0 to 9)

然后回答询问就是用<=r的月之数个数减去<=L的月之数个数,用数位统计的思想,枚举前j-1位跟原数一样,第j位小于原数的那位数字,后面的位任取,枚举数字的和是什么(mo),调用f计算方案数。

uses math;var s,e,d:array[1..200000]of int64;    mid,l,r,ans:int64;    t,n:longint;procedure inf;begin assign(input,'defender.in');reset(input); assign(output,'defender.out');rewrite(output)end;procedure ouf;begin close(input);close(output)end;function check(x:longint):boolean;var i,tot:longint;begin tot:=0; for i:=1 to n do  if (x>=s[i]) then begin   tot:=tot+((min(x,e[i])-s[i]) div d[i])+1  end; if tot and 1=0 then exit(true) else exit(false)end;procedure init;var i:longint;begin readln(n); ans:=0; fillchar(s,sizeof(s),0); fillchar(e,sizeof(e),0); fillchar(d,sizeof(d),0); for i:=1 to n do readln(s[i],e[i],d[i]); l:=0;r:=maxlongint; while l<=r  do begin  mid:=(l+r)>>1;  if check(mid) then l:=mid+1 else r:=mid-1 end; ans:=0; for i:=1 to n do begin  if (l>=s[i])and(l<=e[i])and((l-s[i]) mod d[i]=0) then inc(ans) end; if ans and 1=0 then writeln('There''s no weakness. ') else writeln(l,' ',ans)end;begin inf; readln(t); for t:=1 to t do init; oufend.

const mo=1<<31-1;max=1073741819;var m1,n,m:longint;    ans:int64;    d,dis:array[0..1000]of longint;    b,c:array[1..1000,0..2000]of longint;    t:array[0..4096]of longint;function min(x,y:longint ): longint;begin  if d[x]<d[y] then exit(x) else exit(y)end;procedure change(x,w:longint);begin  d[x]:=w;x:=(x+m1)>>1;  while x<>0 do begin    t[x]:=min(t[x<<1],t[x<<1+1]);    x:=x>>1  endend;procedure dij;var i,x,ne,j:longint;    tot:int64;begin fillchar(d,sizeof(d),127); change(1,0); while d[t[1]]<max do begin   x:=t[1];dis[x]:=d[x];change(x,max);   for i:=1 to b[x,0] do begin     ne:=b[x,i];     if d[ne]<>max then      if dis[x]+c[x,i]<d[ne] then change(ne,dis[x]+c[x,i])   end end; for i:=2 to n do begin   tot:=0;  for j:=1 to b[i,0] do begin   ne:=b[i,j];   if dis[ne]+c[i,j]=dis[i] then inc(tot)  end;  ans:=(ans*tot)mod mo endend;procedure origin;var i:longint;begin  m1:=1;  while m1<=n+2 do m1:=m1<<1;  for i:=1 to n do t[i+m1]:=iend;procedure init;var i,x,y,z:longint;begin  readln(n,m);  for i:=1 to m do begin    readln(x,y,z);    inc(b[x,0]);b[x,b[x,0]]:=y;c[x,b[x,0]]:=z;    inc(b[y,0]);b[y,b[y,0]]:=x;c[y,b[y,0]]:=z  end;  origin;  ans:=1;  dij;  writeln(ans)end;begin  assign(input,'castle.in'); reset(input);  assign(output,'castle.out'); rewrite(output);   init;  close(input); close(output);end.

第三题打表的。。。