记录编号 262369 评测结果 AAAAAAAAAA
题目名称 [NOI 2000]算符破译 最终得分 100
用户昵称 Gravatarppfish 是否通过 通过
代码语言 C++ 运行时间 5.004 s
提交时间 2016-05-20 16:32:19 内存使用 0.34 MiB
显示代码纯文本
#include <bits/stdc++.h>
using namespace std;

template<typename T>inline void Read(T &x)
{
    int f = 1;
    char t = getchar();
    while (t < '0' || t > '9') {
        if (t == '-') f = -1;
        t = getchar();
    }
    x = 0;
    while (t >= '0' && t <= '9') {
        x = x * 10 + t - '0';
        t = getchar();
    }
    x *= f;
}

template<typename T>inline void Write(T x)
{
    static int output[20];
    int top = 0;
    if (x < 0) putchar('-'), x = -x;
    do {
        output[++top] = x % 10;
        x /= 10;
    } while (x > 0);
    while (top > 0) putchar('0' + output[top --]);
    putchar('\n');
}

template<typename T>inline void chkmin(T &x, T y) { if (x > y) x = y; }
template<typename T>inline void chkmax(T &x, T y) { if (x < y) x = y; }

const int maxn = 1005;
const int sigma = 13;
const int maxlen = 14;
const char uti[] = "=+*0123456789";

int n;
int len[maxn];
char str[maxn][maxlen];

bool ban[sigma];
bool fst[sigma];
bool end[sigma];
bool ineql[sigma];
bool okeql[sigma];
bool adj[sigma][sigma];
int st[maxn];
int ed[maxn];
vector<pair<int, int> > neighbor[sigma];

bool used[sigma];
int to[sigma];

bool nosol = true;
int res[sigma][sigma];

void input()
{
    Read(n);
    for (int i = 1; i <= n; i++) {
        scanf("%s", str[i] + 1);
        len[i] = strlen(str[i] + 1);
        for (int j = 1; j <= len[i]; j++) {
            if (str[i][j] - 'a' >= sigma) {
                puts("noway");
                exit(0);
            }
        }
    }
}

long long calc(char *re, int l, int r)
{
    static long long num[maxlen];
    static long long qn[maxlen];
    static char opr[maxlen];
    static char s[maxlen];
    int ol = 0;
    int nl = 0;
    int nt = 0;
    long long cnt;
    for (int i = l; i <= r; i++) {
        if (isalpha(re[i])) {
            s[i] = uti[to[re[i] - 'a']];
        } else {
            s[i] = re[i];
        }
    }
    if (!isdigit(s[l]) || !isdigit(s[r])) return -1;
    for (int i = l; i <= r; i++) {
        if (!isdigit(s[i])) opr[++ol] = s[i];
        else {
            cnt = s[i] - '0';
            while (i + 1 <= r && isdigit(s[i + 1])) {
                cnt = cnt * 10 + s[i + 1] - '0';
                i ++;
            }
            num[++nl] = cnt;
        }
    }
    qn[++nt] = num[1];
    for (int i = 1; i <= ol; i++) {
        if (opr[i] == '*') {
            qn[nt] = qn[nt] * num[i + 1];
        } else {
            qn[++nt] = num[i + 1];
        }
    }
    long long res = 0;
    while (nt > 0) res += qn[nt --];
    return res;
}

void prepare()
{
    static int appear[sigma];
    for (int i = 0; i < sigma; i++) okeql[i] = true;
    for (int i = 1; i <= n; i++) {
        memset(appear, 0, sizeof(appear));
        for (int j = 1; j <= len[i]; j++) {
            appear[str[i][j] - 'a'] ++;
            ineql[str[i][j] - 'a'] = true;
        }
        for (int j = 0; j < sigma; j++) {
            okeql[j] &= (appear[j] == 1);
            okeql[j] &= (str[i][1] - 'a' != j);
            okeql[j] &= (str[i][len[i]] - 'a' != j);
        }
        for (int j = 1; j < len[i]; j++) {
            adj[str[i][j] - 'a'][str[i][j + 1] - 'a'] = true;
            adj[str[i][j + 1] - 'a'][str[i][j] - 'a'] = true;
        }
        fst[str[i][1] - 'a'] = true;
        end[str[i][len[i]] - 'a'] = true;
    }
    static set<pair<int, int> > g[sigma];
    pair<int, int> foo;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j < len[i]; j++) {
            g[str[i][j] - 'a'].insert(make_pair(j == 1 ? -1 : str[i][j - 1] - 'a', str[i][j + 1] - 'a'));
        }
    }
    for (int i = 0; i < sigma; i++) {
        for (set<pair<int, int> >::iterator it = g[i].begin(); it != g[i].end(); it++) {
            neighbor[i].push_back(*it);
        }
    }
}

vector<int> remain;

void fillmax(char s[maxlen], int l, int r)
{
    for (int i = l; i <= r; i++) {
        if (to[s[i] - 'a'] == -1) {
            s[i] = '9';
        }
    }
}

void fillmin(char s[maxlen], int l, int r)
{
    for (int i = l, last = -1; i <= r + 1; i++) {
        if (to[s[i] - 'a'] == -1 && last == -1) last = i;
        if ((to[s[i] - 'a'] != -1 || i == r + 1) && last != -1) {
            if (i - last == 1) {
                s[last] = '0';
            } else {
                s[last] = '1';
                for (int j = last + 1; j < i; j++) s[j] = '0';
            }
            last = -1;
        }
    }
}

void split()
{
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= len[i]; j++) {
            if (to[str[i][j] - 'a'] == 0) {
                ed[i] = j - 1;
                st[i] = j + 1;
                break;
            }
        }
    }
}

bool checkrange()
{
    char tmp[maxlen];
    for (int i = 0; i < sigma; i++) {
        if (to[i] != -1) {
            for (int j = i; j < sigma; j++) {
                if (to[j] != -1) {
                    if (adj[i][j]) {
                        return false;
                    }
                }
            }
        }
    }
    long long lmax, rmax;
    long long lmin, rmin;
    for (int i = 1; i <= n; i++) {
        memcpy(tmp, str[i], sizeof(str[i]));
        fillmax(tmp, 1, len[i]);
        lmax = calc(tmp, 1, ed[i]);
        rmax = calc(tmp, st[i], len[i]);
        memcpy(tmp, str[i], sizeof(str[i]));
        fillmin(tmp, 1, len[i]);
        lmin = calc(tmp, 1, ed[i]);
        rmin = calc(tmp, st[i], len[i]);
        if (lmax < rmin || lmin > rmax) return false;
    }
    return true;
}

bool prezero()
{
    int pr, nx;
    for (int i = 0; i < sigma; i++) {
        if (to[i] == 3) {
            for (int j = 0; j < (int)neighbor[i].size(); j++) {
                pr = neighbor[i][j].first;
                nx = neighbor[i][j].second;
                if ((pr == -1 || (to[pr] < 3 && to[pr] != -1)) && (to[nx] == -1 || to[nx] >= 3)) {
                    return true;
                }
            }
        }
    }
    return false;
}

bool checkall()
{
    long long r1, r2;
    for (int i = 1; i <= n; i++) {
        r1 = calc(str[i], 1, ed[i]);
        r2 = calc(str[i], st[i], len[i]);
        if (r1 == -1 || r2 == -1 || r1 != r2) return false;
    }
    return true;
}

void dfs(int cur)
{
    if (cur == (int)remain.size()) {
        if (checkall()) {
            nosol = false;
            for (int i = 0; i < sigma; i++) {
                if (to[i] != -1) {
                    res[i][to[i]] ++;
                } else {
                    ban[i] = true;
                }
            }
        }
        return;
    }
    for (int i = 3; i < sigma; i++) {
        if (!used[i]) {
            used[i] = true;
            to[remain[cur]] = i;
            if (i != 3 || (i == 3 && !prezero())) dfs(cur + 1);
            used[i] = false;
            to[remain[cur]] = -1;
        }
    }
}

void enumopr(int cur)
{
    if (cur == 1) split();
    if (cur == 3) {
        if (checkrange()) {
            remain.clear();
            for (int i = 0; i < sigma; i++) {
                if (to[i] == -1 && ineql[i]) {
                    remain.push_back(i);
                }
            }
            dfs(0);
        }
        return;
    }
    for (int i = 0; i < sigma; i++) {
        if (cur == 0 && !okeql[i]) continue;
        if (to[i] == -1 && !fst[i] && !end[i]) {
            to[i] = cur;
            enumopr(cur + 1);
            to[i] = -1;
        }
    }
}

void solve()
{
    memset(to, -1, sizeof(to));
    enumopr(0);
    for (int i = 0; i < sigma; i++) {
        if (ban[i]) continue;
        int cert = -1;
        bool flag = true;
        for (int j = 0; j < sigma; j++) {
            if (res[i][j] > 0) {
                if (cert == -1) cert = j;
                else flag = false;
            }
        }
        if (cert != -1 && flag) {
            printf("%c%c\n", 'a' + i, uti[cert]);
        }
    }
    if (nosol) puts("noway");
}

int main()
{
    //#ifndef ONLINE_JUDGE
    freopen("equation.in", "r", stdin);
    freopen("equation.out", "w", stdout);
    //#endif

    input();
    prepare();
    solve();

    //#ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
    //#endif
    return 0;
}