题目
考古学发现,几千年前古梅文明时期的数学非常的发达,他们懂得多位数的加法和乘法,其表达式和运算规则等都与现在通常所用的方式完全相同(如整数是十进制,左边是高位,最高位不能为零;表达式为中缀运算,先乘后加等),唯一的区别是其符号的写法与现在不同。有充分的证据表明,古梅文明的数学文字一共有 13 个符号,与
0,1,2,3,4,5,6,7,8,9,+,∗,= 这 13 个数字和符号(称为现代算符)一一对应。为了便于标记,我们用 13 个小写英文字母 a,b,…m 代替这些符号(称为古梅算符)。但是,还没有人知道这些古梅算符和现代算符之间的具体对应关系。
在一个石壁上,考古学家发现了一组用古梅算符表示的等式,根据推断,每行有且仅有一个等号,等号左右两边为运算表达式(只含有数字和符号),并且等号两边的计算结果相等。
假设这组等式是成立的,请编程序破译古梅算符和现代算符之间的对应关系。
输入描述
第一行为等式的个数 N (1≤N≤10000),以下 N 行每行为一个等式。
每个等式的长度为 5 个字符到 11 个字符。
输出描述
如果不存在对应关系能够满足这组等式,输出noway。
如果有对应关系能够满足这组等式,输出所有能够确定的古梅算符和现代算符的对应关系。每一行有两个字符,其中第一个字符是古梅算符,第二个字符是对应的现代算符。输出按照字典顺序排序。
样例输入
2 abcdec cdefe
样例输出
a6 b* d= f+
样例说明
在上例中,可能对应的现代表达式为 {6∗2=12,2=1+1},{6∗4=24,4=2+2},{6∗8=48,8=4+4}{6∗2=12,2=1+1},{6∗4=24,4=2+2},{6∗8=48,8=4+4}。可见,能够确定的对应关系只有 aa 对应 66 ,bb 对应 ∗∗ ,dd 对应 ==,ff 对应 ++ ,应该输出;而 c,ec,e 虽然能够找到对应的现代算符使得等式成立,但没有唯一的对应关系,不能输出。其他古梅算符 g,h…mg,h…m 完全不能确定,也不能输出。
代码咯:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<vector>
#include<map>
#include<queue>
#include<string>
#include<bitset>
#include<iomanip>
#include<iostream>
#include<cmath>
using namespace std;
#define rep(i,x,y) for(i=x;i<=y;i++)
#define _rep(i,x,y) for(i=x;i>=y;i--)
#define REP(i,x,y) for(int i=(x);i<=(y);i++)
#define _REP(i,x,y) for(int i=(x);i>=(y);i--)
#define CL(S,x) memset(S,x,sizeof(S))
#define CP(S1,S2) memcpy(S1,S2,sizeof(S2))
#define ALL(x,S) for(__typeof((v).end()) x=S.begin();x!=S.end();x++)
#define pb push_back
#define IN insert
#define ER erase
#define BE begin()
#define ED end()
#define LB lower_bound
#define UB upper_bound
#define mp make_pair
#define fi first
#define se second
#define upmin(x,y) x=min(x,y)
#define upmax(x,y) x=max(x,y)
#define COUT(S,x) cout<<fixed<<setprecision(x)<<S<<endl
template<class T> inline void read(T&x){bool fu=0;char c;for(c=getchar();c<=32;c=getchar());if(c=='-')fu=1,c=getchar();for(x=0;c>32;c=getchar())x=x*10+c-'0';if(fu)x=-x;};
template<class T> inline void read(T&x,T&y){read(x);read(y);}
template<class T> inline void read(T&x,T&y,T&z){read(x);read(y);read(z);}
inline char getc(){char c;for(c=getchar();c<=32;c=getchar());return c;}
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
const int inf=int(1e9);
int T,n,i,j,k,l,p,c;
char a[1111][13];int len[1111];
int w[15];int cnt[13][1111];
bool c2[15],c1[15];int lg2[(1<<10)+10];
int ans[15];
int st[15];bool mark[15];
bool near[128][128];
char eq,mul,add;bool sol;
bool caneq()
{
CL(c1,1);
for(char c='a';c<='m';c++)
rep(i,1,T)
{
bool can2=1;
rep(j,1,len[i])
{
if(j<len[i])near[a[i][j]][a[i][j+1]]=near[a[i][j+1]][a[i][j]]=1;
if(a[i][j]==c)cnt[c-'a'][i]++;
}
if(cnt[c-'a'][i]!=1)can2=0;
if(a[i][1]==c||a[i][len[i]]==c){c1[c-'a']=0;can2=0;}
c2[c-'a']=can2;
}
}
bool D(int x){return x>=0;}
int cl()
{
int i,tot=0;
for(;mark[st[0]-1];st[0]--)
st[st[0]-1]=st[st[0]-1]*st[st[0]];
rep(i,1,st[0])tot+=st[i];st[0]=0;
return tot;
}
bool check(int d)
{
int i,j,k,la=-1,left=-1,right=-1;st[0]=0;
rep(i,1,len[d])
{
int c=w[a[d][i]-'a'];
if(D(c))
if(D(la))st[st[0]]=st[st[0]]*10+c;
else st[++st[0]]=c;
else
{
if(st[0]==0)return 0;
for(;mark[st[0]-1];st[0]--)
st[st[0]-1]=st[st[0]-1]*st[st[0]];
if(c==-3)mark[st[0]]=1;
else if(c==-1)left=cl();
else mark[st[0]]=0;
}
la=c;
}
right=cl();
return left==right;
}
void go(int d,int nl,int S) //dfs
{
bool ppp=1;rep(i,0,12)if(!(ans[i]==w[i]||ans[i]==-200)){ppp=0;break;}if(ppp)return;
if(d>T)
{
//rep(i,0,12) printf("%c : %d\n",'a'+i,w[i]);printf("end\n");
sol=1;
rep(i,0,12)if(w[i]!=inf)
{
if(ans[i]==-100)ans[i]=w[i];
else if(ans[i]!=w[i])ans[i]=-200;
}
else ans[i]=-200;
return;
}
else
{
if(nl>len[d])
{
if(check(d))
go(d+1,1,S);
return;
}
int cc=a[d][nl]-'a';
if(w[cc]==inf)
{
for(int S2=S;S2;S2-=S2&-S2)
{
int t=lg2[S2&-S2];
if(nl==1&&t==0&&w[a[d][2]-'a']>0)continue;
w[cc]=t;
go(d,nl+1,S-(S2&-S2));
w[cc]=inf;
}
}
else go(d,nl+1,S);
}
}
void print()
{
int i;
rep(i,0,12)
if(ans[i]>=-3)
{
putchar('a'+i);
if(ans[i]==-3)putchar('*');
else if(ans[i]==-2)putchar('+');
else if(ans[i]==-1)putchar('=');
else putchar('0'+ans[i]);
putchar('\n');
}
if(!sol)printf("noway\n");
}
int g,lw[15],rw[15];
void clw(int&L,int&R){L=R=0;for(;g;g--)upmax(L,lw[g]),R=max(rw[g],R)+(R>0);}
bool predfs()
{
int d,i,j,la,Llw,Lrw,Rlw,Rrw;
rep(d,1,T){
g=0;la=-1;
rep(i,1,len[d]){
int c=w[a[d][i]-'a'];
if(c==inf){if(la<0)g++,lw[g]=rw[g]=0;lw[g]++;rw[g]++;}
else{
if(g==0)return 0;
for(;mark[g-1];g--) lw[g-1]+=lw[g]-1,rw[g-1]+=rw[g];
if(c==-3)mark[g]=1;
else if(c==-2)mark[g]=0;
else if(c==-1)clw(Llw,Lrw);
}
la=c;
}
clw(Rlw,Rrw);
if(Lrw<Rlw||Rrw<Llw)
{
return 0;
}
}
return 1;
}
int main()
{
//freopen("eqution.in","r",stdin);freopen("eqution.out","w",stdout);
read(T);rep(i,1,T)scanf("%s",a[i]+1),len[i]=strlen(a[i]+1);
rep(i,0,10)lg2[1<<i]=i;
caneq();
rep(i,0,12)ans[i]=-100;
for(eq='a';eq<='m';eq++)if(c2[eq-'a'])
for(mul='a';mul<='m';mul++)if(c1[mul-'a'])
for(add='a';add<='m';add++)if(c1[add-'a'])
if(eq!=mul&&add!=mul&&eq!=add)
if(!near[eq][mul]&&!near[eq][add]&&!near[mul][add])
{
rep(i,0,12)w[i]=inf;w[eq-'a']=-1;w[add-'a']=-2;w[mul-'a']=-3;
if(!predfs())continue;
go(1,1,(1<<10)-1);
}
print();
return 0;
}

被折叠的 条评论
为什么被折叠?



