【问题描述】
给你n根火柴棍,你可以拼出多少个形如“A+B=C”的等式?等式中的A、B、C是用火柴棍拼出的整数(若该数非零,则最高位不能是0)。用火柴棍拼数字0-9的拼法如图所示:
注意:
1. 加号与等号各自需要两根火柴棍
2. 如果A≠B,则A+B=C与B+A=C视为不同的等式(A、B、C>=0)
3. n根火柴棍必须全部用上
【输入】
输入文件matches.in共一行,又一个整数n(n<=24)。
【输出】
输出文件matches.out共一行,表示能拼成的不同等式的数目。
【输入输出样例1】
matches.in |
matches.out |
14 |
2 |
【输入输出样例1解释】
2个等式为0+1=1和1+0=1。
【输入输出样例2】
matches.in |
matches.out |
18 |
9 |
解题报告
【问题简述】给n根火柴棒,问能拼出多少种形如“A+B=C”的等式。
【题目类型】枚举或者搜索
【解题分析】题目中给定N<=24,除去等号和加号要用的4个外还有20个火柴棒可以摆放。初始化读入N时可以减去4,剩下就是两个加数所需要的火柴棒数目。
procedure Init;
begin
readln(n);
dec(n,4); {除掉‘=’和‘+’的4根火柴}
end;
和与加数中较大的一个数位数相同或者大一。理想情况下11111和11111,可是另一个加数为0也有6个火柴棒的花费,4个“1”的情况也不可能,所以和枚举到“1111”就可以了。(事实证明也是如此的,因为1比其他字母少用很多火柴),时间效率已经完全可以承受了。
具体操作时,先枚举和,在枚举其中一个加数,另一个加数可以用和减去枚举的加数得到。
for i:=0 to 1111 do //枚举和
for j:=0 to i do //枚举加数
begin
k:=i-j; //相减得到另一个加数
if a[i]+a[j]+a[k]=n then inc(ans); //火柴数和为n则计数器加一
end;
每个数的花费火柴数是可以预处理得到的。
for i:=0 to 9 do
a[i]:=c[i];
for i:=10 to 1111 do
a[i]:= a[i div 10] +a[i mod 10]; //预处理每个数所需要的火柴数
数组a |
a[0] |
a[1] |
a[2] |
a[3] |
a[4] |
a[5] |
a[6] |
a[7] |
a[8] |
a[9] |
数字 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
所需火柴数 |
6 |
2 |
5 |
5 |
4 |
5 |
6 |
3 |
7 |
6 |
如数字12需要的火柴数为:
a[12]= a[12 div 10]+ a[12 mod 10]
=a[1]+a[2]
=2+5
=7
【参考程序】
//By LYLtim
const c:array[0..9]of byte=(6,2,5,5,4,5,6,3,7,6);
var n,s:byte;
a:array[0..1111]of byte;
procedure init;
var i:word;
begin
assign(input,'matches.in');reset(input);
readln(n);
dec(n,4);
for i:=0 to 9 do a[i]:=c[i];
for i:=10 to 1111 do a[i]:=a[i div 10]+a[i mod 10];
close(input);
end;{init}
procedure work;
var i,j,k:word;
begin
s:=0;
for i:=0 to 1111 do
for j:=0 to i do
if a[i]+a[i-j]+a[j]=n then inc(s);
end;{work}
procedure print;
begin
assign(output,'matches.out');rewrite(output);
writeln(s);
close(output);
end;{print}
begin{main}
init;
work;
print;
end.
【输入输出样例2解释】
9个等式为:
0+4=4
0+11=11
1+10=11
2+2=4
2+7=9
4+0=4
7+2=9
10+1=11
11+0=11