[NOIP1998 提高组] 进制位

#如何高效记录并整理编程学习笔记?#

题目描述

著名科学家卢斯为了检查学生对进位制的理解,他给出了如下的一张加法表,表中的字母代表数字。 例如:

\def\arraystretch{2} \begin{array}{c||c|c|c|c} \rm + & \kern{.5cm} \rm \mathclap{L} \kern{.5cm} & \kern{.5cm} \rm \mathclap{K} \kern{.5cm} & \kern{.5cm} \rm \mathclap{V} \kern{.5cm} & \kern{.5cm} \rm \mathclap{E} \kern{.5cm} \\ \hline\hline \rm L & \rm L & \rm K & \rm V & \rm E \\ \hline \rm K & \rm K & \rm V & \rm E & \rm \mathclap{KL} \\ \hline \rm V & \rm V & \rm E & \rm \mathclap{KL} & \rm \mathclap{KK} \\ \hline \rm E & \rm E & \rm \mathclap{KL} & \rm \mathclap{KK} & \rm \mathclap{KV} \\ \end{array}+LKVE​LLKVE​KKVEKL​VVEKLKK​EEKLKKKV​​

其含义为:

L+L=LL+L=L,L+K=KL+K=K,L+V=VL+V=V,L+E=EL+E=E

K+L=KK+L=K,K+K=VK+K=V,K+V=EK+V=E,K+E=KLK+E=KL

\cdots⋯

E+E=KVE+E=KV

根据这些规则可推导出:L=0L=0,K=1K=1,V=2V=2,E=3E=3。

同时可以确定该表表示的是 44 进制加法。

输入格式

第一行一个整数 nn(3\le n\le93≤n≤9)表示行数。

以下 nn 行,每行包括 nn 个字符串,每个字符串间用空格隔开。)

若记 s_{i,j}si,j​ 表示第 ii 行第 jj 个字符串,数据保证 s_{1,1}=\texttt +s1,1​=+,s_{i,1}=s_{1,i}si,1​=s1,i​,|s_{i,1}|=1∣si,1​∣=1,s_{i,1}\ne s_{j,1}si,1​=sj,1​ (i\ne ji=j)。

保证至多有一组解。

输出格式

第一行输出各个字母表示什么数,格式如:L=0 K=1 \cdots⋯ 按给出的字母顺序排序。不同字母必须代表不同数字。

第二行输出加法运算是几进制的。

若不可能组成加法表,则应输出 ERROR!

输入输出样例

输入 #1复制

5
+ L K V E
L L K V E
K K V E KL
V V E KL KK
E E KL KK KV

输出 #1复制

L=0 K=1 V=2 E=3
4

说明/提示

NOIP1998 提高组 第三题

题目分析

  1. 3 \leq n \leq93≤n≤9,也即数字的个数 N \leq 8N≤8。
  2. 研究样例发现,NN 与进制 RR,以及数字对应两位数个数 MM 与数字本身 SS 具有

N = R, M = SN=R,M=S

的关系,下面给出具体证明。


证明

1. 证:N = RN=R。

  • 由题意可知,每个字母代表着不同的数字,所以 R \geq NR≥N 必然成立
  • 设加法表中每个数字分别为 a_i, i \in [0, N - 1]ai​,i∈[0,N−1]。
  • 若 R > NR>N,则存在有 k \in [0, R - 1]k∈[0,R−1],满足 k \ne a_i, i \in [0, N - 1]k=ai​,i∈[0,N−1]。
  • 因为在 RR 进制下,二数相加最大可以达到 TT,而

\begin{aligned} T & = 2(R - 1) \\ & = R + (R - 2) \\ & = (1r)_R \end{aligned}T​=2(R−1)=R+(R−2)=(1r)R​​

  • 其中 r = R - 2r=R−2。
  • 例:在 3 进制下,T = (2)_3 + (2)_3 = (11)_3T=(2)3​+(2)3​=(11)3​。
  • 所以一定会出现加法表中两数字相加等于 kk 或等于 (1k)_R(1k)R​ 的情况,或者 k = 1k=1 时加和等于 (1x)_R, x \in [0, R - 2](1x)R​,x∈[0,R−2] 的情况,使得 kk 出现在加法表上,这与 k \ne a_i, i \in [0, N - 1]k=ai​,i∈[0,N−1] 相矛盾,因此 R \ngtr NR≯N。
  • 而由题目分析可知,N = RN=R 是可以成立的。
  • 因此,在加法表合法的情况下,N \equiv RN≡R,证毕。

2. 证:M = SM=S。

  • 由 1. 可知,N = RN=R,且加法表中最高为两位数
  • 因为只有在 S + x \geq RS+x≥R 时,(S)_R + (x)_R(S)R​+(x)R​ 才能为两位数,且 xx 为 RR 进制下的数字,则可列出以下的不等方程组

\begin{cases} S + x \geq R \\ x \leq R - 1 \end{cases}{S+x≥Rx≤R−1​

  • 解得方程解集为 x \in [R - S, R - 1]x∈[R−S,R−1]。
  • 所以 M = (R - 1) - (R - S) + 1 = SM=(R−1)−(R−S)+1=S,证毕。

结论

  • 因此,题目分析中的两个猜想都成立,我们以此为基础打出代码。
  • 先计算出每个字母所代表的数字(通过猜想 2),然后验证加法表是否匹配即可。

AC代码

#include <bits/stdc++.h>
using namespace std;
int n, S[13], mp[13];
char str[13][13][3];

bool add(int a, int b) {
	int sum = S[a] + S[b], ch = str[a][b][0] - 'A' + 1; //计算加和,取第一位
	if (sum >= n - 1) { //有进位时,高位一定为1
		if (strlen(str[a][b]) != 2 || mp[1] != ch) {
			return 0; //若str[a][b]不为两位数或者第一位不为1,返回错误
		} else {
			sum -= n - 1; //减掉高位,取低位
			ch = str[a][b][1] - 'A' + 1;
		}
	}
	if (mp[sum] != ch) {
		return 0; //不匹配则返回错误
	}
	return 1;
}

int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%s", str[1][i]);
	}
	int M;
	bool flag = 0;
	for (int i = 2; i <= n; i++) {
		M = 0;
		for (int l = 1; l <= n; l++) {
			scanf("%s", str[i][l]);
			if (strlen(str[i][l]) > 1) {
				M++; //计算两位数个数
			}
		}
		S[i] = M; //记录字母对应数字
		if (flag == 0 && mp[M]) { //查重
			flag = 1;
		}
		mp[M] = str[i][1][0] - 'A' + 1; //记录数字对应字母以查重
	}
	if (flag) { //重复错误
		printf("ERROR!");
		return 0;
	}
	for (int i = 2; i <= n; i++) {
		for (int l = 2; l <= n; l++) {
			if (add(i, l) == 0) { //加起来检验加法表是否匹配
				printf("ERROR!"); //不匹配错误
				return 0;
			}
		}
	}
	for (int i = 2; i <= n; i++) {
		printf("%c=%d ", str[i][1][0], S[i]);
	}
	printf("\n%d", n - 1);
	return 0;
}
  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值