NOI2000 算符破译

题目

考古学发现,几千年前古梅文明时期的数学非常的发达,他们懂得多位数的加法和乘法,其表达式和运算规则等都与现在通常所用的方式完全相同(如整数是十进制,左边是高位,最高位不能为零;表达式为中缀运算,先乘后加等),唯一的区别是其符号的写法与现在不同。有充分的证据表明,古梅文明的数学文字一共有 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;
}

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值