NOI2014 全国互测Round2

数据包:http://pan.baidu.com/s/1pJNSkL9

 

T1:

我们先直接用矩阵快速幂暴力

首先是0维,f1=1,f2=1

然后推出下一维的f1'和f2'

下一维的f1'和f2'其实就是f1+f2+f3+....+fn和f2+f3+f4+...+fn+1

所以f1'=sn,f2'=s(n+1)-f1

所以可以klogn求出答案

但是我们做了很多相同的事情,求sn和s(n+1)的时候求出来的矩阵是一样的

所以可以是logn+k的

但是既然是一样的其实f1,f2推到f1'和f2'是可以快速幂的

于是就变成了logn+logk的了

 1 const
 2         h=1000000007;
 3 type
 4         matrix=array[1..3,1..3]of int64;
 5 const
 6         d:matrix=((1,0,0),(1,0,1),(0,1,1));
 7 var
 8         n,k:int64;
 9         t:longint;
10         a,b,c:matrix;
11 
12 operator *(a,b:matrix)c:matrix;
13 var
14     i,j,k:longint;
15 begin
16     fillchar(c,sizeof(c),0);
17     for i:=1 to 3 do
18       for j:=1 to 3 do
19         for k:=1 to 3 do
20           c[i,j]:=(c[i,j]+a[i,k]*b[k,j])mod h;
21 end;
22 
23 procedure main;
24 var
25     i:longint;
26 begin
27         read(n,k);
28         b:=d;
29         fillchar(a,sizeof(a),0);
30         for i:=1 to 3 do
31           a[i,i]:=1;
32         while n>0 do
33           begin
34             if n and 1=1 then a:=a*b;
35             b:=b*b;
36             n:=n>>1;
37           end;
38         b:=a*d;
39         fillchar(c,sizeof(c),0);
40         c[1,1]:=a[2,1];
41         c[2,1]:=a[3,1];
42         c[1,2]:=(b[2,1]-1+h)mod h;
43         c[2,2]:=b[3,1];
44         fillchar(a,sizeof(a),0);
45         for i:=1 to 3 do
46           a[i,i]:=1;
47         while k>0 do
48           begin
49             if k and 1=1 then a:=a*c;
50             c:=c*c;
51             k:=k>>1;
52           end;
53         writeln((a[1,1]+a[2,1])mod h);
54 end;
55 
56 begin
57         read(t);
58         while t>0 do
59           begin
60             dec(t);
61             main;
62           end;
63 end.
View Code

 

T2:

首先有一个结论,那个函数是递增的

然后我们可以证明这样一个结论

假设现在sg最大为k,那么现在最后k+1个sg组成的集合一定是0...k

若现在P[m]>=k+1,那么显然sg[m]=k+1

若现在P[m]=k,那么sg[m]=sg[m-k]

可以用数学归纳法证明

又因为maxsg<=10^5

于是就维护这个sg的序列

 

 

T3:

又是合并的思想

首先我们想一下什么情况父亲会和儿子合并(首先把不可能有收益的儿子删掉,且按最低血量限制排序)

若合并之后血量最低限制不变就一定要合并

若父亲现在没有收益就一定要合并

用可并堆或者启发式合并维护

大概就是这样,具体看solution

  1 const
  2     maxn=200200;
  3     inf=100000000;
  4 type
  5     node=record
  6       size,lc,rc,pay,gain:longint;
  7     end;
  8 var
  9     first,next,last,d:array[0..maxn*2]of longint;
 10     f:array[0..maxn]of node;
 11     n,t,time,tot:longint;
 12 
 13 procedure swap(var x,y:longint);
 14 var
 15     t:longint;
 16 begin
 17     t:=x;x:=y;y:=t;
 18 end;
 19 
 20 procedure insert(x,y:longint);
 21 begin
 22     inc(tot);
 23     last[tot]:=y;
 24     next[tot]:=first[x];
 25     first[x]:=tot;
 26 end;
 27 
 28 function max(x,y:longint):longint;
 29 begin
 30     if x>y then exit(x);
 31     exit(y);
 32 end;
 33 
 34 function merge(a,b:longint):longint;
 35 begin
 36     if (a=0) or (b=0) then exit(a+b);
 37     if f[b].pay<f[a].pay then swap(a,b);
 38     f[a].rc:=merge(f[a].rc,b);
 39     if f[f[a].rc].size>f[f[a].lc].size then swap(f[a].lc,f[a].rc);
 40     f[a].size:=f[f[a].lc].size+f[f[a].rc].size+1;
 41     exit(a);
 42 end;
 43 
 44 procedure dfs(x,fa:longint);
 45 var
 46     i:longint;
 47 begin
 48     i:=first[x];
 49     d[x]:=0;
 50     while i<>0 do
 51       begin
 52         if last[i]<>fa then
 53         begin
 54           dfs(last[i],x);
 55           d[x]:=merge(d[x],d[last[i]]);
 56         end;
 57         i:=next[i];
 58       end;
 59     while (d[x]<>0) and ((f[x].pay>=f[d[x]].pay) or (f[x].gain-f[x].pay<=0)) do
 60       begin
 61         if f[x].gain>=f[d[x]].pay then inc(f[x].gain,f[d[x]].gain-f[d[x]].pay)
 62         else
 63           begin
 64             f[x].pay:=f[x].pay+f[d[x]].pay-f[x].gain;
 65             f[x].gain:=f[d[x]].gain;
 66           end;
 67         d[x]:=merge(f[d[x]].lc,f[d[x]].rc);
 68       end;
 69     if f[x].gain-f[x].pay<=0 then d[x]:=0
 70     else d[x]:=merge(d[x],x);
 71 end;
 72 
 73 procedure main;
 74 var
 75     i,x,y,hp:longint;
 76 begin
 77     fillchar(first,sizeof(first),0);
 78     tot:=0;
 79     read(n,t);
 80     for i:=1 to n do
 81       begin
 82         read(f[i].gain);
 83         if f[i].gain>0 then f[i].pay:=0
 84         else f[i].pay:=-f[i].gain;
 85         if f[i].gain<0 then f[i].gain:=0;
 86         f[i].lc:=0;
 87         f[i].rc:=0;
 88         f[i].size:=1;
 89       end;
 90     for i:=1 to n-1 do
 91       begin
 92         read(x,y);
 93         insert(x,y);
 94         insert(y,x);
 95       end;
 96     inc(n);
 97     f[n].pay:=0;
 98     f[n].gain:=inf;
 99     f[n].size:=1;
100     f[n].lc:=0;
101     f[n].rc:=0;
102     insert(t,n);
103     insert(n,t);
104     dfs(1,0);
105     hp:=0;
106     while d[1]<>0 do
107       begin
108         if hp<f[d[1]].pay then break;
109         inc(hp,f[d[1]].gain-f[d[1]].pay);
110         d[1]:=merge(f[d[1]].lc,f[d[1]].rc);
111       end;
112     if hp>=inf then writeln('escaped')
113     else writeln('trapped');
114 end;
115 
116 begin
117     read(time);
118     while time>0 do
119       begin
120         dec(time);
121         main;
122       end;
123 end.
View Code

 

posted @ 2014-05-28 16:19  Randolph87  阅读(262)  评论(1编辑  收藏  举报