Problem description |
We want to have a great SWERC at Porto this year and we approached this challenge in several ways. We even framed it as a word addition problem, similar to the classic SEND+MORE=MONEY, where each letter stands for a single digit (0, 1, 2, ..., 8, 9) that makes the arithmetic operation correct. In word additions different letters cannot be assigned the same digit and the leftmost letter in a word cannot be zero (0). In particular, a single letter term cannot be zero. |
Input |
A line with an integer n, followed by n lines containing a word each with maximum length of 10 letters. The first n-1 words are the terms to be added and the last line is the result. |
Output |
A single line with an integer: the number of solutions of the word addition problem given as input. |
Sample Input |
3 GREAT SWERC PORTO 3 SEND MORE MONEY 5 TOO GOOD TO BE TRUE |
Sample Output |
6 1 93 |
Problem Source |
HNU Contest |
题意:
给出你一个字母组成的加法式子,在右对齐之后,前n-1个相加得到第n个字符串,要求你对每个字母赋值0~9,每个字母代表的数字不能一样,且没有前导0,有几种赋值方法
思路:
直接对于每个字母分别尝试不同的赋值,搜索下去
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <math.h>
#include <bitset>
#include <algorithm>
#include <climits>
using namespace std;
#define ls 2*i
#define rs 2*i+1
#define UP(i,x,y) for(i=x;i<=y;i++)
#define DOWN(i,x,y) for(i=x;i>=y;i--)
#define MEM(a,x) memset(a,x,sizeof(a))
#define W(a) while(a)
#define gcd(a,b) __gcd(a,b)
#define LL long long
#define N 20005
#define INF 0x3f3f3f3f
#define EXP 1e-8
#define rank rank1
const int mod = 1000000007;
int n,letter[20],cot,len[20],hsh[200],num[200],ans;
char str[20][20];
int check()
{
int i,j,k;
for(i = 0; i<n; i++)//前导0不行
{
if(num[str[i][0]]==0)
return 0;
}
int jin = 0;//进位
for(j = 0; j<len[n-1]; j++)//从右边(个位)开始算
{
if(num[str[n-1][len[n-1]-1-j]]==-1) return 1;//这个字母没有被赋值,返回并往下搜
int sum = jin;
for(i = 0; i<n-1; i++)
{
if(len[i]-1-j<0) continue;
if(num[str[i][len[i]-1-j]]==-1) return 1;//这个字母没有被赋值,返回并往下搜
sum+=num[str[i][len[i]-1-j]];
}
if(sum%10!=num[str[n-1][len[n-1]-1-j]]) return 0;//对应位之和与最后一个不等
jin=sum/10;
}
return !jin;//进位为0则解决了
}
void dfs(int cnt)
{
int i;
if(cnt==-1)
{
ans++;
return;
}
for(i = 0; i<10; i++)//给字母尝试所有不同的赋值赋值
{
if(hsh[i]==0)
{
hsh[i] = 1;
num[letter[cnt]] = i;
if(check())//赋值可行则继续进行
dfs(cnt-1);
hsh[i] = 0;
num[letter[cnt]] = -1;
}
}
}
int main()
{
int i,j,k;
while(~scanf("%d",&n))
{
MEM(hsh,0);
cot = -1;
for(i = 0; i<n; i++)
{
scanf("%s",str[i]);
len[i] = strlen(str[i]);
for(j = 0; j<len[i]; j++)
{
if(!hsh[str[i][j]])
{
hsh[str[i][j]] = 1;
letter[++cot] = str[i][j];//记录所有字母
}
}
}
ans = 0;
MEM(hsh,0);
MEM(num,-1);
dfs(cot);
printf("%d\n",ans);
}
return 0;
}