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

 

你可能感兴趣的:(round)