一开始就想到一个暴力的做法(虽然也知道正解应该是后缀自动机)
把每一个字符串的每一个前缀都倒着加入字典树
然后就变成了经典的树博弈(根节点不能取,因为根是空的)
sg函数为,子树sg的xor和加权值(除根节点外权值都为1,因为每一个节点都只代表一个字符串)
但是这样是n方的,不过不会后缀自动机所以只好暴力
用后缀自动机的话就是建parent树,然后做带权值的树博弈(其实和普通的树博弈差不多,普通的只是权值都为1而已,权值为这个节点代表的字符串个数)
1 {$M 50000000} 2 const 3 maxn=2000010; 4 type 5 node=record 6 go:array['0'..'9']of longint; 7 step,fa:longint; 8 end; 9 10 var 11 sam:array[0..maxn]of node; 12 first,stop,next,min:array[0..maxn]of longint; 13 s,ans:ansistring; 14 tot,last,t,num:longint; 15 16 procedure add(x:char); 17 var 18 now,new,q:longint; 19 begin 20 inc(tot); 21 now:=tot; 22 fillchar(sam[now].go,sizeof(sam[now].go),0); 23 sam[now].step:=sam[last].step+1; 24 while (last<>0)and(sam[last].go[x]=0) do 25 begin 26 sam[last].go[x]:=now; 27 last:=sam[last].fa; 28 end; 29 if last=0 then sam[now].fa:=1 30 else 31 begin 32 q:=sam[last].go[x]; 33 if sam[q].step=sam[last].step+1 then sam[now].fa:=q 34 else 35 begin 36 inc(tot); 37 new:=tot; 38 sam[new]:=sam[q]; 39 sam[q].fa:=new; 40 sam[now].fa:=new; 41 sam[new].step:=sam[last].step+1; 42 while (last<>0)and(sam[last].go[x]=q) do 43 begin 44 sam[last].go[x]:=new; 45 last:=sam[last].fa; 46 end; 47 end; 48 end; 49 last:=now; 50 end; 51 52 procedure insert(x,y:longint); 53 begin 54 inc(num); 55 stop[num]:=y; 56 next[num]:=first[x]; 57 first[x]:=num; 58 min[y]:=sam[x].step+1; 59 end; 60 61 function dfs(x:longint):longint; 62 var 63 i:longint; 64 begin 65 dfs:=0; 66 i:=first[x]; 67 while i<>0 do 68 begin 69 dfs:=dfs xor dfs(stop[i]); 70 i:=next[i]; 71 end; 72 inc(dfs,sam[x].step-min[x]+1); 73 end; 74 75 procedure main; 76 var 77 i:longint; 78 begin 79 readln(s); 80 for i:=1 to tot do 81 first[i]:=0; 82 last:=1; 83 tot:=1; 84 fillchar(sam[1].go,sizeof(sam[1].go),0); 85 for i:=1 to length(s) do 86 add(s[i]); 87 for i:=2 to tot do 88 insert(sam[i].fa,i); 89 if dfs(1)=1 then writeln('codechef') 90 else writeln('topcoder'); 91 end; 92 93 begin 94 assign(input,'game.in'); 95 reset(input); 96 assign(output,'game.out'); 97 rewrite(output); 98 readln(t); 99 while t<>0 do 100 begin 101 main; 102 dec(t); 103 end; 104 close(input); 105 close(output); 106 end.
2.期望面积
(qs.pas/c/cpp/in/out)
Description
给定平面上n个点及其出现的概率,问这n个点中出现的那些点组成的凸包面积期望是多少,如果凸包退化为直线则视其面积为0 保证不出现三点共线
Input
首先输入一个整数n (0 < n ≤ 100).,给定点的个数,之后n行每行输入两个整数x,y(-1000 ≤ x, y ≤ 1000),和一个小数p(0 ≤ p ≤ 1)表示n个点的坐标及其出现的概率,输入数据保证p最多有4位小数
对于1%的数据n<=2
对另外于29%的数据n<=3
对于100%的数据 0<n<=100, -1000 ≤ x, y ≤ 1000,0 ≤ p ≤ 1
Output
输出期望面积,答案保留6位小数,具体格式见sample output
Sample Input
3
0 0 0.1
1 0 0.1
1 1 0.1
Sample Output
0.000500
暴力想法,枚举每一种情况,然后计算凸包面积,再计算期望(考场上只想到拿前面的n<=3的情况)
虽然不可行,但是暴力总是提供基本思想
打完暴力就有想法了,求完凸包再求面积,我们是怎么求面积的呢,一般都是用叉积求的吧
然后我们发现当i->j这个有向线段算进面积的时候当且仅当i和j都出现且在i->j右边的点都没有出现
所以i->j这条有向线段的贡献就是叉积(点i,点j)*pi*pj*П(1-pk(k在i->j右方)),因为没有三点共线所以不要想太多,没有特殊情况
O(n^3)
1 const 2 maxn=105; 3 var 4 x,y,p:array[0..maxn]of double; 5 n:longint; 6 ans:double; 7 8 procedure init; 9 var 10 i:longint; 11 begin 12 read(n); 13 for i:=1 to n do 14 read(x[i],y[i],p[i]); 15 end; 16 17 function cj(x1,y1,x2,y2:double):double; 18 begin 19 exit(x1*y2-y1*x2); 20 end; 21 22 procedure work; 23 var 24 i,j,k:longint; 25 s:double; 26 begin 27 for i:=1 to n do 28 for j:=1 to n do 29 if i<>j then 30 begin 31 s:=cj(x[i],y[i],x[j],y[j])*p[i]*p[j]; 32 for k:=1 to n do 33 if (k<>i)and(k<>j) then 34 if cj(x[k]-x[i],y[k]-y[i],x[j]-x[i],y[j]-y[i])<=0 then s:=s*(1-p[k]); 35 ans:=ans+s; 36 end; 37 write(abs(ans/2):0:6); 38 end; 39 40 begin 41 init; 42 work; 43 end.
第三题待码.........