题目
其实这个题只要知道他是 n n n 进制的,就可以轻松写出暴力代码。
因为它有 n n n 个不同的数,而如果是 n + 1 n + 1 n+1 进制就会有一些数不能用给定字母表示出来,如果是 n − 1 n - 1 n−1 进制就会有两个数是一样的,但是题目要求任意两数都不相同。
理解了为什么是 n n n 进制后,就可以打出暴力代码。
可以枚举每一个数分别是什么,用 next_premutation
,再判断其正确性,如果每一个加法结果都正确,就输出结果,走人。如果判断到最后还没有找到,就输出ERROR!
,由于
3
≤
n
≤
9
3 \le n \le 9
3≤n≤9,所以可以将加法结果当成一个
n
n
n 进制数处理,但是还是用的int
类型,操作时细节比较多,务必注意。
AC Code:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <list>
#include <set>
#include <map>
using namespace std;
int n;
string s[20][20];
map<char, int> m;
int ans[10];
int change(string str) {
int len = str.size();
int ret = 0;
for (int i = 0; i < len; i ++) {
ret *= (n - 1);
ret += ans[m[str[i]]];
}
int a1 = ret % (n - 1);
int a2 = ret / (n - 1);
return a2 * 10 + a1;
}
bool check(int i, int j) {
int tmp = change(s[i][j]);
int a1 = (ans[i] + ans[j]) % (n - 1);
int a2 = (ans[i] + ans[j]) / (n - 1);
if (a2 * 10 + a1 == tmp) return 1;
else return 0;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i ++) {
for (int j = 1; j <= n; j ++) {
cin >> s[i][j];
}
}
for (int i = 1; i <= n; i ++) {
m[s[i][1][0]] = i;
}
for (int i = 2; i <= n; i ++) {
ans[i] = i - 2;
}
do {
bool flag = 0;
for (int i = 2; i <= n; i ++) {
for (int j = 2; j <= n; j ++) {
if (!check(i, j)) flag = 1;
}
}
if (flag == 0) {
for (int i = 2; i <= n; i ++) {
cout << s[i][1] << '=' << ans[i] << ' ';
}
cout << '\n' << n - 1;
return 0;
}
} while (next_permutation(ans + 2, ans + 1 + n));
cout << "ERROR!";
return 0;
}