洛谷P1013 [NOIP1998 提高组] 进制位 题解
题意:
著名科学家卢斯为了检查学生对进位制的理解,他给出了如下的一张加法表,表中的字母代表数字。 例如:
其含义为:
$L+L=L$,$L+K=K$,$L+V=V$,$L+E=E$
$K+L=K$,$K+K=V$,$K+V=E$,$K+E=KL$
$\cdots$
$E+E=KV$
根据这些规则可推导出:$L=0$,$K=1$,$V=2$,$E=3$。
同时可以确定该表表示的是 $4$ 进制加法。
输入格式:
第一行一个整数 $n$($3\le n\le9$)表示行数。
以下 $n$ 行,每行包括 $n$ 个字符串,每个字符串间用空格隔开。)
若记 $s_{i,j}$ 表示第 $i$ 行第 $j$ 个字符串,数据保证 $s_{1,1}=\texttt +$,$s_{i,1}=s_{1,i}$,$|s_{i,1}|=1$,$s_{i,1}\ne s_{j,1}$ ($i\ne j$)。
保证至多有一组解。
输出格式:
第一行输出各个字母表示什么数,格式如:
L=0 K=1
$\cdots$ 按给出的字母顺序排序。不同字母必须代表不同数字。第二行输出加法运算是几进制的。
若不可能组成加法表,则应输出
ERROR!
。
容易证明,只有 $N$ 进制恰好有 $N$ 个数。
那么我们只要找到有多少数加上当前的数要进位,就可以求出当前的数是多少了
时间复杂度 $\mathcal{O}(n^2)$
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)())
int n,ans[15],mp[26]; char s[15][15][3];
bool check(int x, int y)
{
int sum = ans[x] + ans[y];
int cur = s[x][y][1] - 'A';
if(sum >= n - 1 && mp[cur] != 1) return 0;
if(sum >= n - 1) sum -= n - 1, cur = s[x][y][2] - 'A';
if(mp[cur] != sum) return 0;
return 1;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// freopen("check.in","r",stdin);
// freopen("check.out","w",stdout);
cin >> n;
for(int i = 1; i <= n; i++) cin >> (s[1][i] + 1);
for(int i = 2; i <= n; i++)
{
int cnt = 0;
for(int j = 1; j <= n; j++)
{
cin >> (s[i][j] + 1);
cnt += strlen(s[i][j] + 1) >= 2;
}
ans[i] = cnt; mp[s[i][1][1] - 'A'] = cnt;
}
for(int i = 2; i <= n; i++)
for(int j = 2; j <= n; j++)
if(!check(i, j)) return cout << "ERROR!" << '\n', 0;
for(int i = 2; i <= n; i++)
cout << s[i][1][1] << '=' << ans[i] << " \n"[i == n];
cout << n - 1 << '\n';
return 0;
}