列表

详情


NC16866. [NOI2000]算符破译

描述

考古学发现,几千年前古梅文明时期的数学非常的发达,他们懂得多位数的加法和乘法,其表达式和运算规则等都与现在通常所用的方式完全相同(如整数是十进制,左边是高位,最高位不能为零;表达式为中缀运算,先乘后加等),唯一的区别是其符号的写法与现在不同。有充分的证据表明,古梅文明的数学文字一共有13个符号,与 0,1,2,3,4,5,6,7,8,9,+,*,= 这13个数字和符号(称为现代算符)一一对应。为了便于标记,我们用13个小写英文字母a,b,…m代替这些符号(称为古梅算符)。但是,还没有人知道这些古梅算符和现代算符之间的具体对应关系。

在一个石壁上,考古学家发现了一组用古梅算符表示的等式,根据推断,每行有且仅有一个等号,等号左右两边为运算表达式(只含有数字和符号),并且等号两边的计算结果相等。

假设这组等式是成立的,请编程序破译古梅算符和现代算符之间的对应关系。

输入描述

第一行为等式的个数N(1≤ N ≤ 1000),以下N行每行为一个等式。
每个等式的长度为5个字符到11个字符。

输出描述

如果不存在对应关系能够满足这组等式,输出“noway”和一个换行/回车符。
如果有对应关系能够满足这组等式,输出所有能够确定的古梅算符和现代算符的对应关系。每一行有两个字符,其中第一个字符是古梅算符,第二个字符是对应的现代算符。输出按照字典顺序排序。

示例1

输入:

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}。可见,能够确定的对应关系只有a对应6,b对应*,d对应=,f对应+,应该输出;而{c,e}虽然能够找到对应的现代算符使得等式成立,但没有唯一的对应关系,不能输出。其他古梅算符{g,h…m}完全不能确定,也不能输出。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 1420ms, 内存消耗: 372K, 提交时间: 2019-01-07 16:55:27

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
const int MAXL=12,MAXN=1001,LETTER=15,LT=13;
const int EQUAL=-1,PLUS=-2,MULTIPLY=-3,NO=-4,UND=-5;
using namespace std;
struct equation
{
    int len;
    int s[MAXL];
}E[MAXN];
int adjl[LETTER][LETTER];
bool adjm[LETTER][LETTER];
bool ce[LETTER];//可以为等号的字母
bool op[LETTER],appear[100],ava[LETTER],Noway=true;
bool used[LETTER],opu[2];
int Mapp[LETTER],Sp[LETTER];
int P[2][MAXL],L[2];
int N;
void print();
inline int cmp(const void *a,const void *b)
{
    return ((equation *)a)->len-((equation *)b)->len;
}
inline int Max(int a,int b)
{
    return a>b?a:b;
}
void init()
{
    int i,j;
    int te[LETTER];
    char W[MAXL];
    memset(adjm,0,sizeof(adjm));
    scanf("%d",&N);
    for (i=1;i<=LT;i++)
        ce[i]=true;
    for (i=1;i<=N;i++)
    {
        scanf("%s",W);
        E[i].len=strlen(W);
        memset(te,0,sizeof(te));
        for (j=1;j<=E[i].len;j++)
        {
            E[i].s[j]=W[j-1]-'a'+1;
            ava[E[i].s[j]]=true;
            if (j!=1 && j!=E[i].len)
                te[E[i].s[j]]++;
            if (j>1)
                adjm[E[i].s[j]][E[i].s[j-1]]=adjm[E[i].s[j-1]][E[i].s[j]]=true;
        }
        adjm[E[i].s[1]][0]=adjm[0][E[i].s[1]]=true;
        adjm[E[i].s[E[i].s[j]]][0]=adjm[0][E[i].s[E[i].s[j]]]=true;
        for (j=1;j<=LT;j++)
            if (te[j]!=1)
            ce[j]=false;
    }
    for (i=0;i<=LT+1;i++)
    {
        for (j=0;j<=LT+1;j++)
            if (adjm[i][j])
                adjl[i][ ++adjl[i][0] ]=j;
        Mapp[i]=Sp[i]=UND;
    }
    op[0]=true;
    qsort(E+1,N,sizeof(E[0]),cmp);
}
void debug()
{
    int i,j,c;
    for (i=1;i<=N;i++)
    {
        for (j=1;j<=E[i].len;j++)
        {
            c=Mapp[E[i].s[j]];
            if (c>=0) c+='0';
            else if (c==EQUAL) c='=';
            else if (c==PLUS) c='+';
            else if (c==MULTIPLY) c='*';
            printf("%c",c);
        }
        printf("n");
    }
    printf("n");
}
void solution()
{
    int i;
    //debug();
    if (Sp[1]==UND)
        for (i=1;i<=LT;i++)
        {
            Sp[i]=Mapp[i];
            appear[Sp[i]+10]=true;
        }
    else
        for (i=1;i<=LT;i++)
            if (Sp[i]!=Mapp[i])
            {
                Sp[i]=NO;
                appear[Sp[i]+10]=true;
            }
}
int compute(int *P,int L)
{
    int stack[MAXL],top=0,i;
    for (i=1;i<=L;i++)
    {
        if (P[i]>=0)
            stack[++top]=P[i];
        else if (P[i]==MULTIPLY)
            stack[top]=stack[top]*P[++i];
    }
    for (;top>1;top--)
        stack[top-1]+=stack[top];
    return stack[1];
}
void makeequation(int p)
{
    int i,k=0,v;
    L[0]=L[1]=0;
    memset(P,0,sizeof(P));
    for (i=1;i<=E[p].len;i++)
    {
        v=Mapp[E[p].s[i]];
        if (v==EQUAL)
        {
            k=1;
            continue;
        }
        if (v>=0)
        {
            if (i==1 || Mapp[E[p].s[i-1]]<0)
                L[k]++;
            P[k][L[k]]=P[k][L[k]]*10+v;
        }
        else
        {
            P[k][++L[k]]=v;
        }
    }
}
bool check(int p)
{
    int R[2];
    makeequation(p);
    R[0]=compute(P[0],L[0]);
    R[1]=compute(P[1],L[1]);
    return (R[0]==R[1]);
}
void fillequation(int p,int f)
{
    int i,k=0,v;
    L[0]=L[1]=0;
    memset(P,0,sizeof(P));
    for (i=1;i<=E[p].len;i++)
    {
        v=Mapp[E[p].s[i]];
        if (v==EQUAL)
        {
            k=1;f=10-f;
            continue;
        }
        if (v>=0)
        {
            if (i==1 || Mapp[E[p].s[i-1]]<0)
                L[k]++;
            P[k][L[k]]=P[k][L[k]]*10+f;
        }
        else
        {
            P[k][++L[k]]=v;
        }
    }
}
bool limit()
{
    int i;
    int R[2];
    for (i=1;i<=N;i++)
    {
        fillequation(i,1);//左小右大
        R[0]=compute(P[0],L[0]);
        R[1]=compute(P[1],L[1]);
        if (R[0]>R[1])
            return false;
        fillequation(i,9);//左大右小
        R[0]=compute(P[0],L[0]);
        R[1]=compute(P[1],L[1]);
        if (R[0]<R[1])
            return false;
    }
    return true;
}
void computelen(int *P,int L,int &a,int &b)
{
    int stacka[MAXL],stackb[MAXL],top=0,i;
    for (i=1;i<=L;i++)
    {
        if (P[i]>=0)
        {
            stacka[++top]=P[i];
            stackb[top]=P[i];
        }
        else if (P[i]==MULTIPLY)
        {
            stacka[top]=stacka[top]+P[++i]-1;
            stackb[top]=stackb[top]+P[i];
        }
    }
    for (;top>1;top--)
    {
        stacka[top-1]=Max(stacka[top-1],stacka[top]);
        stackb[top-1]=Max(stackb[top-1],stackb[top])+1;
    }
    a=stacka[1];b=stackb[1];
}
bool lenequation(int p)
{
    int i,k=0,v,l0,l1,r0,r1;
    L[0]=L[1]=0;
    memset(P,0,sizeof(P));
    for (i=1;i<=E[p].len;i++)
    {
        v=Mapp[E[p].s[i]];
        if (v==EQUAL)
        {
            k=1;
            continue;
        }
        if (v>=0 || v==UND)
        {
            if (i==1 || Mapp[E[p].s[i-1]]<0)
                L[k]++;
            P[k][L[k]]=P[k][L[k]]+1;
        }
        else
        {
            P[k][++L[k]]=v;
        }
    }
    computelen(P[0],L[0],l0,r0);
    computelen(P[1],L[1],l1,r1);
    return !(r0<l1 || r1<l0);
}
bool possible()
{
    int i;
    for (i=1;i<=N;i++)
    {
        if (!lenequation(i))
            return false;
    }
    return true;
}
void search_number(int p,int k)//第p个等式 第k个字符
{
    int i,C=E[p].s[k];
    bool rfs,lfs;

    for (i=1;i<=LT;i++)
        if (ava[i])
            if (!(Mapp[i]==Sp[i] || Sp[i]==NO))
                break;
    if (i>LT)
        return;

    if (p>N)
    {
        Noway=false;
        solution();
        return;
    }
    rfs= k==E[p].len || Mapp[E[p].s[k+1]]<0;
    lfs= k==1 || Mapp[E[p].s[k-1]]<0;
    if (Mapp[C]==0 && !rfs && lfs)
        return;
    while (Mapp[C]!=UND && k<=E[p].len)
    {
        C=E[p].s[--k];
        rfs= k==E[p].len || Mapp[E[p].s[k+1]]<0;
        lfs= k==1 || Mapp[E[p].s[k-1]]<0;
        if (Mapp[C]==0 && !rfs && lfs)
            return;
    }
    if (k==0)
    {
        if (check(p))
            search_number(p+1,E[p+1].len);
        return;
    }
    for (i=0;i<=9;i++)
    {
        if (used[i])
            continue;
        rfs= k==E[p].len || Mapp[E[p].s[k+1]]<0;
        lfs= k==1 || Mapp[E[p].s[k-1]]!=UND;
        if (i==0 && !rfs && lfs)
            continue;
        Mapp[C]=i;
        used[i]=true;
        search_number(p,k-1);
        used[i]=false;
    }
    Mapp[C]=UND;
}
void search_operator(int k)
{
    int i,j;
    while ((!ava[k] || Mapp[k]!=UND) && k<=LT) k++;
    if (k>LT)
    {
        if (possible() && limit())
            search_number(1,E[1].len);
        return;
    }
    for (i=1;i<=adjl[k][0];i++)
    {
        j=adjl[k][i];
        if (op[j])
            break;
    }
    if (i>adjl[k][0])
    {
            op[k]=true;
            if (!opu[0])
            {
                opu[0]=true;
                Mapp[k]=PLUS;
                search_operator(k+1);
                opu[0]=false;
            }
            if (!opu[1])
            {
                opu[1]=true;
                Mapp[k]=MULTIPLY;
                search_operator(k+1);
                opu[1]=false;
            }
            op[k]=false;
            Mapp[k]=UND;
    }
    search_operator(k+1);
}
void solve()
{
    int i;
    for (i=1;i<=LT;i++)
    {
        if (ce[i] && !adjm[i][0])
        {
            op[i]=true;
            Mapp[i]=EQUAL;
            search_operator(1);
            Mapp[i]=UND;
            op[i]=false;
        }
    }
}
void print()
{
    int i,ud=0,j,other;
    for (i=1;i<=LT;i++)
    {
        if (Sp[i]==UND)
        {
            ud++;
            j=i;
        }
        if (!appear[i])
            other=i;
    }
    for (i=1;i<=LT;i++)
    {
        if (ud==1 && i==j)
        {
            int c=other-10;
            if (c==EQUAL) c='=';
            else if (c==PLUS) c='+';
            else if (c==MULTIPLY) c='*';
            else c-='+';
            printf("%c%c\n",i+'a'-1,c);
            continue;
        }
        if (Sp[i]==UND || Sp[i]==NO )
            continue;
        if (Sp[i]==EQUAL) printf("%c=\n",i+'a'-1);
        else if (Sp[i]==PLUS) printf("%c+\n",i+'a'-1);
        else if (Sp[i]==MULTIPLY) printf("%c*\n",i+'a'-1);
        else printf("%c%d\n",i+'a'-1,Sp[i]);
    }
    if (Noway)
        printf("noway");
    exit(0);
}
int main()
{
    init();
    solve();
    print();
    return 0;
}

C++ 解法, 执行用时: 40ms, 内存消耗: 516K, 提交时间: 2022-06-09 20:55:11

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int INF=int(1e9);
const int MaxN=1010;
int T;
char a[MaxN][15]; 
int len[MaxN],lg2[(1<<10)+10];
int w[15],Ans[15],st[15],cnt[15][MaxN];
bool c1[15],c2[15],mark[15],Map[150][1150];
char Equ,Mul,Add;
bool Solved;

inline int Id(char x) { return x-'a'; }

int calc()
{
    int i,sum=0;
    for(;mark[st[0]-1];st[0]--)
        st[st[0]-1]=st[st[0]-1]*st[st[0]];
    for (int i=1; i<=st[0]; i++) sum+=st[i]; st[0]=0;
    return sum;
}

bool check(int d)
{
    int Last=-1,L=-1,R=-1; st[0]=0;
    for (int i=1; i<=len[d]; i++)
    {
        int c=w[Id(a[d][i])];
        if(c>=0)
            if(Last>=0)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)L=calc();
                    else mark[st[0]]=0;
        }
        Last=c;
    }
    R=calc();
    return L==R;
}

void Dfs(int d,int Now,int S)
{
    bool Flag=1;
    for (int i=0; i<=12; i++) 
        if(!(Ans[i]==w[i] || Ans[i]==-200)){ Flag=0; break; }
    if(Flag) return;
    if(d>T)
    {   
        Solved=1;
        for (int i=0; i<=12; i++) 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(Now>len[d])
        {
            if(check(d)) Dfs(d+1,1,S);
            return;
        }
        int ch=Id(a[d][Now]);
        if(w[ch]==INF)
        {
            for(int S2=S; S2; S2-=S2&-S2)
            {
                int t=lg2[S2&-S2];
                if(Now==1 && t==0 && w[Id(a[d][2])]>0)continue;
                w[ch]=t;
                Dfs(d,Now+1,S-(S2&-S2));
                w[ch]=INF;
            }
        }
        else Dfs(d,Now+1,S);
    }
}

int M,lw[15],rw[15];

void Get_Range(int &L, int &R)
{ 
    L=R=0; 
    for (;M;M--) L=max(L,lw[M]),R=max(rw[M],R)+(R>0); 
}

bool Pre_Dfs()
{
    int Last,L_l,L_r,R_l,R_r;
    for (int d=1; d<=T; d++)
    {
        M=0;Last=-1;
        for (int i=1; i<=len[d]; i++)
        {
            int c=w[Id(a[d][i])];
            if(c==INF)
            { 
                if(Last<0) M++,lw[M]=rw[M]=0; 
                lw[M]++,rw[M]++;
            }
            else
            {
                if(M==0)return 0;
                for(; mark[M-1]; M--) lw[M-1]+=lw[M]-1,rw[M-1]+=rw[M];

                     if(c==-3) mark[M]=1;
                else if(c==-2) mark[M]=0;
                else if(c==-1) Get_Range(L_l,L_r);
            }
            Last=c;
        }
        Get_Range(R_l,R_r);
        if(L_r<R_l || R_r<L_l)
        {
            return 0;
        }
    }
    return 1;
}

int main()
{
    scanf("%d",&T);
    for (int i=1; i<=T; i++) scanf("%s",a[i]+1),len[i]=strlen(a[i]+1);
    for (int i=0; i<=15; i++) lg2[1<<i]=i,Ans[i]=-100;     
    memset(c1,1,sizeof(c1));

    for(char i='a';i<='m';i++)
        for (int j=1; j<=T; j++)
        {
            bool Flag=1;
            for (int k=1; k<=len[j]; k++)
            {
                if(k<len[j]) Map[a[j][k]][a[j][k+1]]=Map[a[j][k+1]][a[j][k]]=1;
                if(a[j][k]==i) cnt[Id(i)][j]++;
            }
            if(cnt[Id(i)][j]!=1) Flag=0;
            if(a[j][1]==i || a[j][len[j]]==i){ c1[i-'a']=0; Flag=0; }
            c2[Id(i)]=Flag;
        }

    for(Equ='a'; Equ<='m'; Equ++) if(c2[Id(Equ)])
        for(Mul='a'; Mul<='m'; Mul++) if(c1[Id(Mul)])
            for(Add='a'; Add<='m'; Add++) if(c1[Id(Add)])
                if(Equ!=Mul && Add!=Mul && Equ!=Add)
                    if(!Map[Equ][Mul] && !Map[Equ][Add] && !Map[Mul][Add])
                    {                 
                        for (int i=0; i<=12; i++) w[i]=INF;
                        w[Id(Equ)]=-1; w[Id(Add)]=-2; w[Id(Mul)]=-3;
                        if(!Pre_Dfs()) continue;
                        Dfs(1,1,(1<<10)-1);
                    }

    for (int i=0; i<=12; i++)
        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(!Solved) printf("noway\n");

    return 0;
}

上一题