所謂蟲食算,就是原先的算式中有一部分被蟲子啃掉了,需要我們根據剩下的數字來判定被啃掉的字母。來看一個簡單的例子:
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.