本解题报告版权归 Ceeji 所有,如需转载请注明出处和本注释。
题目描述
单词方程
二元词是一个由0和1组成的非空串。一个单词方程是一个形如X1X2..Xl=Y1Y2..Yr的等式,其中 Xi 和Yj 是二进制数字 (0 和 1) 或者变量(小写英文字母)。每个变量都代表某个固定长度的二元词,这个长度被称作该变量的长度。要解一个单词方程,我们必须赋给每个变量一个适当长度的二元词(这个二元词的长度必须和变量的长度相等),使得当所有变量都用所对应的二元词替换完毕后,等式两边(替换的来的二元词)相同。
请计算一个给定的单词方程的所有解的总数。
例如:
假设a、b、c、d、e 是长度分别为4、2、4、4、2的变量(a的长度是4,b的长度是2……)。则方程1bad1 = acbe有16组不同的解。
求解任务:
请设计一个程序
从文件ROW.IN中读入方程的总数以及每个方程的信息;
求出每个方程解的个数;
将结果写到文件ROW.OUT中。
输入:
在输入文件ROW.IN的第一行是一个整数x(1<=x<=5),表示文件中包含的方程的总数。接下来的部分包含对于这x个方程的描述。每个方程的描述由6行组成,描述之间没有多余的空行。每个方程用以下格式描述:第一行是一个整数k,0 <= k <= 26,表示当前方程中变量的数目。这k个变量用前k个小写英文字母表示。第二行有k个由空格分隔的正整数,表示变量a、b、…… 的长度。第三行是一个整数l,表示方程左端的长度(即由0、1以及小写英文字母组成的串的长度)。方程左端在下一行中以一个数字和字母组成的串的形式给出,中间不含空格。接下来的两行包含对于方程右端的描述。首先是一个正整数r,表示方程右端的长度。接下来的一行给出方程的右端,表示的方法与左端相同。对于方程的左右两端,所有数字的总数加上所有变量的长度之和(变量每出现一次都计入总长)不会超过10000。
输出:
请将第1..x个方程的解的总数写到输出文件ROW.OUT的第1..x行。
样例输入:
1
5
4 2 4 4 2
5
1bad1
4
acbe
样例输出:
16
解题思路
本解题报告版权归 Ceeji 所有,如需转载请注明出处和本注释。
这道题是典型的并查集。将每个字母的每一位和0、1看作一个节点,然后将左右两端的每一位的节点合并。如果出现0,1同父或字母数为0但左右输入字符串却不相等则输出0,否则输出
q**2
q**2,其中q代表父亲不重复并且父亲和0、1不同的个数。和0、1父亲相同的均被固定,所以结果乘以1,等于没乘。
问题
本解题报告版权归 Ceeji 所有,如需转载请注明出处和本注释。
通过 FreePascal IDE 编译测试无问题,但 Cena 每次评测都随机出错,出错的地点和错误的类型每次都不一样,不知道是什么原因。调查中。如某位神牛能够从鄙人的代码中发现问题,也请提醒一下,谢谢。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | //本解题报告的代码版权归 Ceeji 所有,如需转载请注明出处和本注释。 //By Ceeji //HAOI Test 4 - Problem 2 : Row //Type: Union-find Sets //Date: 2009-4-5 //States: Programing Program Row; Const inf='row.in'; ouf='row.out'; maxn=26; maxl=10000; Var n,u,k:longint; len:array[1..maxn]of integer; str1,str2:ansistring; f1:array['a'..'z',-1..maxl]of char; f2:array['a'..'z',-1..maxl]of integer; ls1,rs1:array[1..maxl]of char; ls2,rs2:array[1..maxl]of integer; b:array['a'..'z',-1..maxl]of boolean; Procedure init; begin assign(input,inf); reset(input); assign(output,ouf); rewrite(output); readln(n); end; Procedure getFather(c:char; p:longint;var d:char;var q:longint); begin if (f1[c,p]=c)and(f2[c,p]=p) then begin d:=c; q:=p; exit; end; getFather(f1[c,p],f2[c,p],d,q); f1[c,p]:=d; f2[c,p]:=q; end; Procedure work; var i,j,l,p,q,y,ff1,ff2,ff3,ff4:longint; c,c1,c2,c3,c4:char; ans:longint; begin readln(k); fillchar(f1,sizeof(f1),0); fillchar(f2,sizeof(f2),0); fillchar(len,sizeof(len),0); fillchar(ls1,sizeof(ls1),0); fillchar(rs1,sizeof(rs1),0); fillchar(ls2,sizeof(ls2),0); fillchar(rs2,sizeof(rs2),0); f1['a',-1]:='a'; f2['a',-1]:=-1; f1['a',0]:='a'; f2['a',0]:=0; for i:=1 to k do begin read(len[i]); c:=chr(96+i); for j:=1 to len[i] do begin f1[c,j]:=c; f2[c,j]:=j; end; end; readln(l); readln(str1); readln(l); readln(str2); if (k=0) then begin if str1=str2 then writeln('1') else writeln('0'); exit; end; p:=length(str1); j:=0; for i:=1 to p do begin c:=str1[i]; if c='0' then begin inc(j); ls1[j]:='a'; ls2[j]:=0; continue; end else if c='1' then begin inc(j); ls1[j]:='a'; ls2[j]:=-1; continue; end else begin q:=len[ord(c)-96]; for y:=1 to q do begin inc(j); ls1[j]:=c; ls2[j]:=y; end; end; end; p:=length(str2); j:=0; for i:=1 to p do begin c:=str2[i]; if c='0' then begin inc(j); rs1[j]:='a'; rs2[j]:=0; continue; end else if c='1' then begin inc(j); rs1[j]:='a'; rs2[j]:=-1; continue; end else begin q:=len[ord(c)-96]; for y:=1 to q do begin inc(j); rs1[j]:=c; rs2[j]:=y; end; end; end; for i:=1 to j do begin getFather(ls1[i],ls2[i],c1,ff1); getFather(rs1[i],rs2[i],c2,ff2); f1[c1,ff1]:=c2; f2[c1,ff1]:=ff2; end; y:=0; q:=0; fillchar(b,sizeof(b),0); getFather('a',0,c3,ff3); getFather('a',-1,c4,ff4); if (c3=c4)and(ff3=ff4) then begin writeln('0'); exit; end; for i:=1 to k do begin if i=1 then p:=-1 else p:=1; for j:=p to len[i] do begin getFather(chr(96+i),j,c1,ff1); if (b[c1,ff1]=false)and(((c1=c3)and(ff1=ff3))=false)and(((c1=c4)and(ff1=ff4))=false) then begin inc(q); b[c1,ff1]:=true; end else if (c1<>'a')or(ff1>0) then inc(y); end; end; writeln(2**q); end; Procedure endPro; begin close(input); close(output); exit; end; {main} begin init; for u:=1 to n do work; endPro; end.{main} |