雀巢杯1&2

现在不是很想写,所以写得比较粗略,大家可以去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]:=-maxlongint
end;
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
  end
end;
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;
 ouf
end.

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;
 ouf
end.

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
  end
end;
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
 end
end;
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]:=i
end;
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.

第三题打表的。。。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值