【问题描述】
所谓虫食算,就是原先的算式中有一部分被虫子啃掉了,需要我们根据剩下的数字来判定被啃掉的字母。来看一个简单的例子:
43#9865#045
+ 8468#6633
44445506978
其中#号代表被虫子啃掉的数字。根据算式,我们很容易判断:第一行的两个数字分别是5和3,第二行的数字是5。
现在,我们对问题做两个限制:
首先,我们只考虑加法的虫食算。这里的加法是N进制加法,算式中三个数都有N位,允许有前导的0。
其次,虫子把所有的数都啃光了,我们只知道哪些数字是相同的,我们将相同的数字用相同的字母表示,不同的数字用不同的字母表示。如果这个算式是N进制的,我们就取英文字母表午的前N个大写字母来表示这个算式中的0到N-1这N个不同的数字:但是这N个字母并不一定顺序地代表0到N-1)。输入数据保证N个字母分别至少出现一次。
BADC
+ CBDA
DCCC
上面的算式是一个4进制的算式。很显然,我们只要让ABCD分别代表0123,便可以让这个式子成立了。你的任务是,对于给定的N进制加法算式,求出N个不同的字母分别代表的数字,使得该加法算式成立。输入数据保证有且仅有一组解。
【样例输入】
5
ABCED
BDACE
EBBAA
【样例输出】
1 0 3 4 2
【解题思路】
本题为NOIP2004第四题,其实也不是那么难(虽然WA了N次……),这道题可以像处理高精度加法一样,模拟笔算,从最后一竖列开始算,一个一个字符去搜,数字从大往小搜(虽然不知道为什么,应该是题目问题……这种搜索的题目大部分都是倒着搜),然后将一竖列满足要求的数字搜出来之后,往前一竖列搜,如果字母都已经存了值,那么就判断是否符合,如果不符合就返回上一层,重新搜索。
【代码实现】
1 var n,i:longint; 2 p1,p2,p3:string; 3 s:array[0..4,0..30] of longint; 4 num:array[0..50] of longint; 5 f,flag:array[0..50] of boolean; 6 function check(x,y:longint):boolean; 7 var i,op,sp:longint; 8 begin 9 for i:=n downto 1 do 10 if (f[s[1,i]])and(f[s[2,i]])and(f[s[3,i]]) then 11 if ((num[s[1,i]]+num[s[2,i]]) mod n<>num[s[3,i]])and((num[s[1,i]]+num[s[2,i]])mod n<>(num[s[3,i]]+n-1)mod n) then 12 exit(false); 13 if y=0 then 14 begin 15 op:=0; 16 for i:=n downto 1 do 17 begin 18 if i+1<>n+1 then 19 if num[s[1,i+1]]+num[s[2,i+1]]+op>=n then//进位 20 op:=1 21 else 22 op:=0; 23 if (num[s[1,i]]+num[s[2,i]])mod n<>(num[s[3,i]]+n-op)mod n then//不相同,返回 24 exit(false); 25 end; 26 write(num[1]); 27 for i:=2 to n do 28 write(' ',num[i]); 29 writeln; 30 halt; 31 end; 32 exit(true); 33 end; 34 procedure dfs(x,y:longint); 35 var i,px,ll:longint; 36 begin 37 if not(check(x,y)) then 38 exit; 39 for i:=1 to n do 40 begin 41 px:=0; 42 if (f[s[1,i]])and(f[s[2,i]])and(f[s[3,i]]) then 43 continue 44 else 45 if (f[s[1,i]])and(f[s[2,i]]) then 46 begin 47 px:=3; 48 ll:=(num[s[1,i]]+num[s[2,i]])mod n; 49 end 50 else 51 if (f[s[1,i]])and(f[s[3,i]]) then 52 begin 53 px:=2; 54 ll:=(num[s[3,i]]+n-num[s[1,i]])mod n; 55 end 56 else 57 if (f[s[2,i]])and(f[s[3,i]]) then 58 begin 59 px:=1; 60 ll:=(num[s[3,i]]+n-num[s[2,i]])mod n; 61 end;//判断是加数。被加数还是和 62 if px<>0 then 63 begin 64 if not(flag[ll]) then 65 begin 66 flag[ll]:=true;//用过了的数字就标记 67 f[s[px,i]]:=true;//同上 68 num[s[px,i]]:=ll; 69 dfs(x,y); 70 flag[ll]:=false; 71 f[s[px,i]]:=false; 72 num[s[px,i]]:=0; 73 end; 74 if px<>3 then 75 ll:=(ll+n-1) mod n 76 else 77 ll:=(ll+1) mod n; 78 if not(flag[ll]) then 79 begin 80 flag[ll]:=true; 81 f[s[px,i]]:=true; 82 num[s[px,i]]:=ll; 83 dfs(x,y); 84 flag[ll]:=false; 85 f[s[px,i]]:=false; 86 num[s[px,i]]:=0; 87 end; 88 exit; 89 end; 90 end; 91 if not(f[s[x,y]]) then 92 begin 93 f[s[x,y]]:=true; 94 for i:=n-1 downto 0 do 95 begin 96 if flag[i] then 97 continue; 98 flag[i]:=true; 99 f[s[x,y]]:=true; 100 num[s[x,y]]:=i; 101 if x=3 then 102 dfs(1,y-1) 103 else 104 dfs(x+1,y); 105 flag[i]:=false; 106 f[s[x,y]]:=false; 107 num[s[x,y]]:=0; 108 end; 109 end 110 else 111 begin 112 if x=3 then 113 dfs(1,y-1) 114 else 115 dfs(x+1,y); 116 end; 117 end; 118 begin 119 readln(n); 120 readln(p1); 121 readln(p2); 122 readln(p3); 123 fillchar(num,sizeof(num),byte(-1)); 124 for i:=1 to n do 125 begin 126 s[1,i]:=ord(p1[i])-ord('A')+1; 127 s[2,i]:=ord(p2[i])-ord('A')+1; 128 s[3,i]:=ord(p3[i])-ord('A')+1; 129 end;//初始化 130 dfs(1,n); 131 end.